> ## 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.

# Passkey вместе с Veriqa

> Добавление passkey после входа через мессенджер сочетает в одном сценарии удобство Veriqa и устойчивость passkey к фишингу.

Вход через мессенджер удобен, но подтверждение в чате ничем не связано с браузером, где откроется
сессия: человек, которого уговорили подтвердить чужой QR-код, отдаёт вход атакующему. Passkey
привязан к адресу вашего приложения и работает только рядом с браузером, поэтому обязательный ключ
защищает от этого тех пользователей, у кого он есть. Veriqa остаётся способом входа и доставляет
кнопку для заведения ключа, а регистрирует и проверяет ключ ваше приложение.

> [!NOTE]
>
> Механизмы для этого сценария в Veriqa уже есть, логику поверх них вы реализуете на своей стороне
> так, как удобно вам, — см. [«Что вы реализуете сами»](#что-вы-реализуете-сами).

## Что Veriqa даёт passkey

Сам по себе passkey требует аккаунта, к которому его привязать, и способа вернуть доступ, если
устройство с ключом потеряно. Когда вход идёт через Veriqa, и то и другое появляется с первым входом:

* **Аккаунт без формы регистрации.** Первый вход через мессенджер даёт вашему приложению идентичность пользователя,
  и аккаунт вы создаёте по ней — без формы, пароля и подтверждения почты, как в сценарии
  [«Вход и регистрация без пароля»](https://veriqa.app/docs/ru/scenarios/passwordless-login.md). Ключ добавляется к уже
  существующему аккаунту.
* **Резервный канал с первого входа.** Аккаунт уже связан с мессенджером человека. Если устройство с
  ключом потеряно, у вас остаётся канал, через который можно связаться с человеком; восстановление
  через него ведите отдельной, более строгой процедурой (см.
  [«На что обратить внимание»](#на-что-обратить-внимание)).
* **Меньше шагов, чем с формой регистрации.** Чтобы войти, человек сканирует QR-код и нажимает
  кнопку в чате, а ключ заводит по ещё одной кнопке в том же чате.

## Что вы реализуете сами

Veriqa passkey не создаёт и не проверяет: регистрацию и проверку ключа ведёт серверная библиотека
WebAuthn вашего стека. Veriqa даёт вход и кнопку в мессенджере после него.

1. **Кнопка в мессенджере после входа.** Задайте постдействие `Redirect` (или пункт-ссылку меню
   `Menu`) с адресом вашей страницы заведения ключа и `{handle}` в нём —
   [Menu и Redirect](https://veriqa.app/docs/ru/reference/configuration.md#menu-и-redirect-сообщение-с-кнопками):

   ```json theme={null}
   {
     "Veriqa": {
       "OpenIddict": {
         "Clients": [
           {
             "ClientId": "app",
             "CompletionBehavior": {
               "ActionByChannel": { "telegram": "Redirect" },
               "RedirectUrl": "https://app.example.com/passkey/add?h={handle}",
               "RedirectButtonText": "Add a passkey"
             }
           }
         ]
       }
     }
   }
   ```

   *Пример синтетический: идентификатор клиента, адрес и подпись кнопки.* Настройки лежат в записи
   клиента, поэтому кнопка приходит после каждого входа в это приложение через Telegram и только в
   чат того, кто подтвердил вход. Остальные каналы, которые показывают кнопки, добавьте в ту же карту.
2. **Страница заведения ключа.** Ссылка из кнопки открывается там, где у человека мессенджер, —
   обычно на телефоне. Ваш сервер обменивает handle и узнаёт, кто вошёл
   (`POST /api/link-handle/redeem` с токеном приложения — см.
   [«Два бота»](https://veriqa.app/docs/ru/scenarios/channel-linking.md#два-бота-передача-пользователя-вашему-боту)),
   получает `sub` и запускает регистрацию WebAuthn для этого `sub`. Ключ создаётся на этом
   устройстве и привязан к адресу вашего приложения. Handle одноразовый и живёт
   `Veriqa:TransactionEngine:CompletedRetentionSeconds` — 600 секунд по умолчанию.
3. **Ключ — только по кнопке.** Не давайте завести ключ из сессии, открытой входом через Veriqa:
   если вход был переслан, эта сессия у атакующего, и он завёл бы к чужому аккаунту свой ключ. Если
   у `sub` ключ уже есть, страница заведения регистрирует новый только после подписи существующим
   ключом: иначе атакующий, уговоривший человека подтвердить пересланный вход, попросит переслать и
   ссылку из кнопки и заведёт свой ключ.
4. **Ключ до сессии.** Получив от Veriqa `id_token`, проверьте, есть ли у `sub` ключ. Если есть,
   запросите подпись ключа в этом же браузере и откройте сессию только после её проверки. Если нет —
   действуйте по своей политике: откройте обычную сессию или предложите завести ключ по кнопке в
   мессенджере.
5. **Обязательный режим.** Для пользователя, который завёл ключ, вход без ключа закройте: пока он
   открыт, атакующий воспользуется им.

## Почему это работает

Атакующий начинает вход в вашем приложении и пересылает QR-код жертве. Жертва подтверждает в своём
мессенджере, и Veriqa отдаёт код авторизации браузеру атакующего. Дальше ваше приложение просит в
этом браузере ключ жертвы. Страница-подделка на чужом адресе подписи для вашего адреса не получит, а
вход ключом с телефона на чужой компьютер требует Bluetooth между ними: по
[RFC 10027](https://www.rfc-editor.org/rfc/rfc10027) (BCP 247, §6.2.3.3) BLE нужен обоим
устройствам. При обязательном ключе, если новые ключи добавляются только существующим, сессию
атакующий не получит.

В терминах BCP 247 для пользователей с обязательным ключом это близость устройств по радио (§6.1.1).
Это и вход, устойчивый к фишингу, перед подтверждением, которое создаёт ваш сервер (§6.1.15). Как
это соотносится с остальными мерами, показано на странице [«Veriqa, BCP 247 и модель угроз»](https://veriqa.app/docs/ru/concepts/cross-device-security.md).

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

* **Защищает только обязательный режим.** Пользователь без ключа или с открытым входом без ключа
  защищён не больше, чем обычным входом через мессенджер.
* **Заведение первого ключа — слабое место.** Ссылка из кнопки действует на предъявителя: кто
  откроет её первым, тот и заведёт ключ к аккаунту, у которого ключа ещё нет. Атакующий, который
  уговорил человека подтвердить чужой вход, может попросить переслать и эту ссылку. Когда ключ у
  аккаунта уже есть, страница добавляет новый только после подписи существующим (шаг 3). Сообщайте
  пользователю о каждом новом ключе по каналу, который у вас есть, и давайте удалить чужой.
* **Нужен Bluetooth или ключ на самом компьютере.** Вход ключом с телефона на компьютер требует
  Bluetooth на обоих устройствах. Где радио запрещено, работает ключ, созданный на самом компьютере:
  заведите первый ключ там, открыв кнопку, например, в настольном мессенджере. Если первый ключ уже
  на телефоне, на таком компьютере ключ не добавить: для этого нужна подпись существующим ключом, а
  ей тоже нужен Bluetooth. Тогда для такого периметра подходит
  [фактор места](https://veriqa.app/docs/ru/scenarios/place-and-identity.md).
* **Не во всех каналах есть кнопка.** Кнопку после входа показывают мессенджеры и вход через аккаунт
  провайдера. Email кнопок не показывает, WhatsApp через Twilio их не отправляет: таким пользователям
  нужен свой путь к ключу, но не из сессии, открытой через Veriqa.
* **Потеря устройства.** Восстановление доступа без ключа — ещё один путь в обход ключа. Ведите его
  отдельной процедурой, строже обычного входа, — см.
  [«Восстановление доступа»](https://veriqa.app/docs/ru/scenarios/account-recovery.md).


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