> ## Documentation Index
> Fetch the complete documentation index at: https://veriqa.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Вход через аккаунт Google или Apple с подтверждением на телефоне

> Устройство входа показывает QR-код, пользователь входит в Google или Apple на своём телефоне и подтверждает вход там же. На устройстве входа пароль не вводится.

Устройство входа показывает QR-код. Пользователь сканирует его телефоном, входит в свой аккаунт
Google или Apple **на телефоне** и подтверждает вход там же, после чего вход завершается на
устройстве. На устройстве входа пароль не вводится вовсе.

От обычной кнопки «Войти через Google» это отличается тем, где вводятся учётные данные. Кнопка
открывает вход у провайдера в браузере того устройства, на котором входят, и логин и пароль Google
вводятся там. Здесь вход у провайдера проходит на телефоне, а устройство входа получает только
результат.

Так работает пример `samples/dotnet/pseudo-channels` из репозитория
([veriqa.app/source](https://veriqa.app/source)). Как его настроить и запустить, сказано в его
`README.md`: нужны публичный HTTPS-адрес, OAuth-клиент Google и Services ID Apple.

## Когда это пригодится

**Устройство, на котором не хочется вводить свои пароли:**

* чужой или общий компьютер;
* рабочее место коллеги;
* компьютер в гостинице, коворкинге или учебном классе;
* киоск или терминал на стойке.

**Поверхность без клавиатуры:**

* телевизор и приставка — пароль пришлось бы набирать пультом;
* киоск с сенсорным экраном;
* устройство с несколькими кнопками;
* экран в переговорной.

## Как это работает

1. Устройство входа открывает обычный вход OpenID Connect через `/connect/authorize`. Страница входа
   Veriqa показывает QR-код со ссылкой [hop-режима](/docs/ru/concepts/hop-mode).
2. Пользователь сканирует QR-код камерой телефона. Телефон открывает hop-страницу узла; если
   включены оба провайдера, пользователь выбирает Google или Apple.
3. Хост примера отправляет телефон к провайдеру по потоку authorization code. Пользователь выбирает
   аккаунт. Если он ещё не вошёл в Google или Apple на телефоне, то входит сейчас и вводит пароль
   провайдера на телефоне.
4. Провайдер возвращает телефон на адрес возврата примера, и хост проверяет полученные claims.
5. Хост сообщает ядру о старте подписанным вебхуком. Ядро задаёт вопрос через адаптер, а адаптер
   сохраняет контекст вопроса для транзакции.
6. Телефон показывает страницу **Confirm the sign-in**: в какое приложение входит пользователь, в
   каком браузере и системе начат вход, место, время начала и аккаунт. Пользователь нажимает
   **Yes, sign me in** или **No**.
7. Хост передаёт ядру ответ подписанным вебхуком: подтверждение или отказ.
8. Устройство входа завершает поток OpenID Connect, телефон показывает итог.

Приложение получает `sub` вида `google-id:<идентификатор пользователя в Google>` или
`apple-id:<идентификатор пользователя в Apple>`, а также `channel_user_id`, `channel_type`, `email`
и `email_verified`.

Если ссылку канала открыть в браузере самого устройства входа, а не сканировать телефоном, поток
сводится к обычному входу у провайдера с той же страницей вопроса. Кросс-девайсной части тогда нет,
но ничего не ломается.

## Зачем вопрос на телефоне

Провайдер может вернуть результат, ничего не спросив: без `prompt` Google показывает экран согласия
только тому, кто ещё не давал приложению доступ, поэтому на телефоне, где выполнен вход в один
аккаунт Google и доступ уже дан, вход пройдёт без единого экрана. Пример передаёт `prompt=select_account`,
чтобы экран выбора аккаунта хотя бы показал, каким аккаунтом идёт вход
([Google: OpenID Connect](https://developers.google.com/identity/openid-connect/openid-connect)).
И сам выбор аккаунта не говорит, **чей** вход
он завершает. Без шага 6 злоумышленник мог бы показать жертве свой QR-код, и её вход в Google молча
завершил бы вход злоумышленника — на его устройстве и под аккаунтом жертвы. Страница вопроса
называет приложение и устройство, с которого начат вход, поэтому жертва может ответить **No**.

Вопрос и ответ привязаны к конкретному входу:

* страница вопроса работает лишь в том браузере, который только что вошёл у провайдера: после
  возврата от провайдера хост ставит ему короткоживущую куку;
* второй аккаунт, вошедший у провайдера для того же входа, не видит ни данных, ни кнопок;
* отменённый или просроченный вход повторно не спрашивается.

Если ядро не раскрывает данные инициатора, страница всё равно спрашивает — тогда над кнопками
остаётся только аккаунт. Что показывается о том, кто начал вход, описано в
[Контексте инициатора](/docs/ru/concepts/initiator-context).

## Чем это не является

Google и Apple — **не встроенные каналы** Veriqa. Это пример, собранный на публичном SPI канала
([Свой канальный адаптер](/docs/ru/guides/custom-channel-adapter)): один класс `IChannelAdapter`
зарегистрирован дважды, как `google-id` и как `apple-id`, и зависит только от
`Veriqa.Core.Contracts`. Роль платформы канала играет сам хост примера.

Это и не канал доставки. За ним нет чата или почтового ящика, поэтому отправить пользователю
сообщение «в канал» нельзя: вопрос «это вы входите?» задаёт страница примера на телефоне. Место
псевдоканалов среди остальных каналов описано в разделе
[Псевдоканалы](/docs/ru/guides/supported-channels#псевдоканалы-google-apple-и-huawei); отдельный сервис для
входа через Google, Apple и Huawei готовится — см. [Следующие релизы](/docs/ru/releases/next).

## На что обратить внимание

* **Сканируйте QR-код системной камерой, а не внутри мессенджера.** Если открыть QR-код или ссылку
  во встроенном браузере приложения, к Google придёт встроенный user-agent, и Google отклонит вход с
  ошибкой `disallowed_useragent`
  ([Google: OAuth 2.0 policies, «Use secure browsers»](https://developers.google.com/identity/protocols/oauth2/policies),
  [Google: ошибки авторизации](https://developers.google.com/identity/protocols/oauth2/web-server)).
* **Номера телефона нет.** В ID token Google документирует claims `sub`, `email`, `email_verified`,
  `name`, `given_name`, `family_name`, `picture` и `locale`
  ([Google: OpenID Connect](https://developers.google.com/identity/openid-connect/openid-connect)),
  а Apple принимает scopes `name` и `email`
  ([Apple: запрос авторизации](https://developer.apple.com/documentation/signinwithapple/incorporating-sign-in-with-apple-into-other-platforms)).
  Если приложению нужен подтверждённый номер телефона, нужен канал, в котором номер есть.
* **Apple: адрес почты может быть адресом пересылки.** Пользователь может выбрать анонимный адрес,
  который пересылает письма на настоящий. Письма на него доходят только с доменов отправителя,
  зарегистрированных в Apple
  ([Apple: private email relay service](https://developer.apple.com/documentation/signinwithapple/communicating-using-the-private-email-relay-service)).
  Считайте `email` адресом для связи, а не идентификатором: идентификатор — `sub`.
* **Apple: имени нет.** Пример запрашивает только `openid email`. Apple передаёт имя отдельным полем
  `user` ответа авторизации, а не claim в ID token
  ([Apple: запрос авторизации](https://developer.apple.com/documentation/signinwithapple/incorporating-sign-in-with-apple-into-other-platforms)),
  и только при первом входе пользователя
  ([Apple: authenticating users](https://developer.apple.com/documentation/signinwithapple/authenticating-users-with-sign-in-with-apple)).
  Поэтому отображаемое имя пользователя Apple — его адрес почты.
* **Состояние хранится в памяти.** Контекст вопроса и итог хранятся в процессе хоста, пока живёт
  транзакция (`Veriqa:TransactionEngine:TransactionTtlSeconds`). Перезапуск сбрасывает все
  незавершённые входы.

## См. также

* [Поверхности входа](/docs/ru/scenarios/surfaces) — откуда можно начать вход и чем поверхности
  отличаются для интеграции.
* [Smart TV и поверхности без клавиатуры](/docs/ru/scenarios/smart-tv) — вход там, где вводить нечем.
* [Свой канальный адаптер](/docs/ru/guides/custom-channel-adapter) — SPI, на котором написан адаптер
  примера.
* [Примеры](/docs/ru/samples) — все примеры репозитория.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.