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

# OIDC + Veriqa: разбор

> Что Veriqa делает внутри стандартного OIDC-потока и чего намеренно не делает.

Этот разбор — для разработчиков, которые работали с OIDC, но не с Veriqa. Он показывает, где
именно Veriqa встраивается в стандартный поток и где останавливается.

## Что такое OIDC за один экран

OpenID Connect — тонкий слой идентичности поверх OAuth 2.0. Приложение получает два токена:
`id_token` (кто пользователь) и `access_token` (доступ к API). Приложение не проверяет пароли
само — оно доверяет это **issuer'у** (authorization server), а тот возвращает подписанные
токены.

## Authorization Code Flow + PKCE

Стандартный безопасный поток для веб- и десктоп-приложений:

1. Приложение редиректит пользователя на `/authorize` issuer'а (с `state`, `nonce` и
   PKCE-параметрами).
2. Пользователь аутентифицируется на стороне issuer'а.
3. Issuer возвращает короткоживущий `code` на зарегистрированный `redirect_uri`.
4. Приложение меняет `code` (+ PKCE `code_verifier`) на токены через `/token`.

PKCE с методом `S256` обязателен для публичных клиентов — он защищает обмен `code` от
перехвата.

## Куда вставляется Veriqa

Veriqa встаёт **между шагами 2 и 3** — на месте «пользователь аутентифицируется». Вместо формы
логина issuer открывает **транзакцию Veriqa**: показывает QR / точку входа, ждёт подтверждения
в доверенном канале, формирует `ClaimsPrincipal` из результата и отдаёт его OpenIddict для
выпуска `code`. Дальше — обычный OIDC (`code` → `/token` → токены).

<Card title="Полный поток по шагам" icon="diagram-project" href="/docs/ru/concepts/auth-flow">
  От старта транзакции до выпуска токенов OpenIddict.
</Card>

Ключевое: Veriqa **не заменяет OpenIddict** — выпуск токенов, discovery, JWKS, refresh
остаются за ним. Veriqa лишь поставляет аутентификацию пользователя через доверенный канал.

## Адаптер канала в потоке

Адаптер канала (MAX / Telegram / WhatsApp / другие мессенджеры / Email) связывает транзакцию с
конкретным
мессенджером: доставляет запрос подтверждения пользователю, принимает его ответ и возвращает
в транзакцию resolved identity. Каждый канал — отдельный адаптер, набор расширяем.

## Resolved identity и claims

После подтверждения Veriqa формирует снимок идентичности и маппит его в OIDC claims:

| Claim | Значение |
| - | - |
| `sub` | Стабильный идентификатор субъекта (обязателен) |
| `amr` | Метод аутентификации — тип канала подтверждения (`telegram`, `whatsapp`, `max`, `email`). В `id_token` — **массивом строк** даже при одном методе: `"amr": ["telegram"]` (OIDC Core 1.0 §2). Тот же метод виден и в `access_token` / ответе `/connect/userinfo` |
| `auth_time` | Момент завершения аутентификации |
| `name`, `email`, … | Дополнительные claims из resolved identity — по каналу и запрошенным scopes |
| `channel_type`, `channel_user_id` | Канал подтверждения и идентификатор пользователя в нём — **только при запрошенном scope `channel`** |

`channel` — кастомный scope Veriqa: он и есть гейт канальных claims. Не запросили — эти два claim
не попадут ни в `access_token`, ни в `id_token`, ни в ответ `/connect/userinfo`. Добавьте `channel`
в запрашиваемые scopes RP и в `AllowedScopes` клиента, если ваше приложение их читает.

`avatar` — второй кастомный scope Veriqa, и он гейтит `picture`. Значение — само изображение в виде
URI `data:image/…;base64,…` (канал с публичной ссылкой на фото, например MAX, может отдать `https`
URL). Claim едет только в `access_token`, поэтому доходит до вас только через `/connect/userinfo`; в
`id_token` он не попадает никогда. Запросите `avatar` (и добавьте его в `AllowedScopes` клиента),
заберите claims из userinfo (`GetClaimsFromUserInfoEndpoint = true` в ASP.NET Core); нет `picture` —
нет аватара. В ASP.NET Core `picture` по умолчанию в principal не маппится, и маппить его не нужно:
data URI в cookie аутентификации раздувает заголовки запросов. Берите изображение из JSON userinfo в
`OnUserInformationReceived` и храните в своём хранилище.

`/connect/userinfo` отдаёт только те claims, что разрешены scopes и конфигурацией. Набор
маппинга переопределяется своим `IClaimsMapper`.

<Warning>
  `preferred_username` — подсказка, а не идентичность. В канале Email (режим Push) в него
  попадает display name отправителя — строка, которую пишет сам отправитель в заголовке `From`.
  SPF, DKIM и DMARC её **не подтверждают**: они проверяют домен и адрес, но не отображаемое имя.
  Veriqa санитизирует значение (убирает bidi-override и управляющие символы, обрезает по длине),
  но подтвердить его не может.

  Идентификатор пользователя — только `sub`; подтверждённый адрес — `email` рядом с
  `email_verified`. Не сопоставляйте по `preferred_username` учётные записи и не показывайте его
  как проверенное имя.
</Warning>

## Step-up и подтверждение в терминах OIDC

`2FA` и `step-up` — не отдельные типы транзакции, а надстройки: `2FA` над `login`, `step-up`
над `confirmation`. Это та же транзакционная модель Veriqa с дополнительным контекстом, так что
подтверждение чувствительного действия проходит тем же доверенным каналом, что и обычный вход.

## Чего Veriqa НЕ делает

Veriqa — **не** identity provider, **не** account manager и **не** система регистрации. Он
добавляет способ аутентификации и linking к вашей существующей системе, не становясь
владельцем пользовательской базы.

## Дальше

<CardGroup cols={2}>
  <Card title="Быстрый старт .NET" icon="rocket" href="/docs/ru/quickstart/dotnet">
    Подключите Veriqa к ASP.NET Core-хосту.
  </Card>

  <Card title="Hardening к продакшну" icon="shield-check" href="/docs/ru/guides/hardening">
    Чек-лист перед продакшном.
  </Card>
</CardGroup>


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