Один код, любое развёртывание. Приложению не важно, где работает Veriqa — в облаке Veriqa,
в вашем контейнере Docker или службой (systemd либо служба Windows) на вашей машине. Варианты
различаются только адресом issuer’а и тем, где заведён клиент; код приложения ниже одинаков
для всех, а переключение сводится к одному
server_metadata_url.1. Установите библиотеку
Рекомендуемая библиотека — Authlib (актуальная линия 1.8.x):flask — фреймворк, на котором построен
пример ниже; requests — то, на чём построены интеграции Authlib с Flask и Django, а у Starlette и
FastAPI вместо него httpx, так что ставьте нужный вашему фреймворку. Без любого из этих пакетов
первый же запуск падает на блоке импортов в начале app.py с ModuleNotFoundError — ещё до
обращения к Veriqa.
Требуется Python 3.10 или новее — это минимум, объявленный пакетом. Готовые интеграции есть для
Flask, Django, Starlette и FastAPI; ниже показан Flask, у остальных тот же реестр OAuth и те же
вызовы.
2. Заведите клиента на стороне Veriqa
Veriqa Cloud сейчас недоступен — строки про облако описывают контракт его API. Используйте
self-hosted; подробности — в Veriqa Cloud.
У self-hosted две поставки, и для этой страницы они равнозначны. Сервер работает в контейнере
Docker — быстрый старт self-hosted — либо ставится из архива юнитом
systemd или службой Windows, без Docker и без рантайма .NET на машине —
установка службой ОС. Выбор определяет способ поставки сервера, а не
регистрацию клиента, адрес issuer’а и код ниже.
Секрет не обязателен. Минимальный рабочий набор —
issuer, client_id, redirect_uri:
public-клиент с PKCE, и это дефолт облака. Confidential-клиент нужен, только если вы хотите
аутентифицировать серверное приложение секретом; в облаке секрет выпускается отдельным явным
действием на экране Applications и показывается один раз.
redirect_uri сверяется точным совпадением — wildcard не поддерживаются. Регистрируйте ровно
тот URL, который отдаёт ваш маршрут callback. Для примера на Flask ниже, запущенного как в
шаге 7, это http://127.0.0.1:5000/authorize — регистрируйте ровно его и
открывайте приложение в той же форме хоста (127.0.0.1, а не localhost): URL callback’а строит
url_for(..., _external=True) из хоста входящего запроса, а сверка на стороне Veriqa буквальная.
3. Зарегистрируйте провайдера
server_metadata_url включает discovery: Authlib сам читает
/.well-known/openid-configuration и находит остальные эндпоинты.
Значения код берёт из окружения, поэтому задайте их в той оболочке, из которой будете запускать
приложение. Первые три — то, что вы получили на шаге 2, четвёртая — ваша собственная:
FLASK_SECRET_KEY Veriqa не выдаёт — это ваша произвольная случайная строка, ключ, которым Flask
подписывает cookie сессии. В систему контроля версий он не попадает, и в каждом окружении значение
своё. Варианту public VERIQA_CLIENT_SECRET не нужен: у public-клиента секрета нет вовсе. Не задать
любую из переменных, которые читает выбранный вариант, — и первый же запуск падает с KeyError ещё
на импорте app.py, до первого маршрута.
Каждый вариант ниже — целиком «голова» app.py: приложение Flask, секрет сессии, нужный Authlib, и
регистрация провайдера. Маршруты шага 4 кладутся в этот же файл, ниже.
VERIQA_ISSUER.
4. Опишите маршруты входа
app.py
authorize_access_token() сам обменивает код на токены и разбирает id_token — готовые claims
лежат в token["userinfo"], отдельно вызывать userinfo-эндпоинт не нужно. code_verifier для
PKCE библиотека генерирует и хранит сама, руками его передавать не требуется.
Между /login и /authorize работает Veriqa: пользователь видит страницу входа с QR и списком
каналов и подтверждает вход в мессенджере на телефоне.
/ — то, куда браузер попадает в конце: пока в сессии пусто, маршрут отправляет на /login, а
после успешного входа показывает, что в неё положено, — словарь, возвращённый из view Flask,
сериализуется в JSON, так что результат виден без единого шаблона.
5. Прочитайте claims
Базовый набор Veriqa кладёт в токены сама:
Claims канала выдаются только по scope
channel:
Без запрошенного scope
channel эти два claim не попадают ни в один токен — и, следовательно,
не появляются в ответе userinfo, который зеркалит access_token. Именно по ним приложение различает
привязанные каналы, поэтому для сценария привязки аккаунта scope обязателен.
6. Ограничьте вход конкретным каналом
Стандартный OIDC-параметрacr_values формата channel:{тип} сужает выбор на странице входа.
Дополнительные именованные аргументы authorize_redirect уходят в authorize-запрос как есть:
channel:telegram channel:whatsapp) — пользователь выбирает из
перечисленных. Без параметра доступны все включённые на сервере каналы.
7. Контрольная точка
Запустите приложение из каталога, где лежитapp.py, в той оболочке, где экспортированы переменные
шага 3:
http://127.0.0.1:5000 — именно из этого адреса строится redirect_uri,
зарегистрированный на шаге 2.
1
Проверьте discovery
curl $VERIQA_ISSUER/.well-known/openid-configuration возвращает метаданные с https-URL.2
Запустите вход
Откройте
http://127.0.0.1:5000/login — браузер должен уйти на страницу Veriqa с QR и
каналами.3
Подтвердите на телефоне
Подтвердите запрос в доверенном канале; браузер вернётся на ваш маршрут
/authorize, а тот
перенаправит его на /.4
Проверьте claims
/ показывает сессию в виде JSON: sub заполнен, а channel_type несёт канал, которым
подтверждён вход, — он остаётся null, если scope channel не запрашивался.Дальше
Сценарии интеграции
Привязка канала, повторное подтверждение и подтверждение действия — на уровне HTTP.
Быстрый старт: self-hosted
Развернуть свой issuer в Docker.
Установка службой ОС
Тот же issuer без Docker — systemd или служба Windows, из архива.
OIDC + Veriqa: разбор
Где Veriqa встаёт в стандартный поток.
Hardening к продакшну
Что проверить перед выпуском.