Авторизация через Дiю: как мы интегрировали национальную цифровую идентификацию в юридическую платформу
Паспорт в смартфоне — теперь ключ к юридическому AI. Мы интегрировали Дiя.Подпись для авторизации: deep link на мобильном, QR-код на десктопе, ECDSA + SHA256 для хеширования, и юрист подтверждает личность тем же приложением, которым показывает документы на блокпосте. Без паролей. Без регистрации. Один тап — и вы в системе.
Авторизация через Дiю: как мы интегрировали национальную цифровую идентификацию
Паспорт в смартфоне — теперь ключ к юридическому AI.
Почему Дiя, а не ещё один OAuth
Юридическая платформа работает с конфиденциальными данными. Google OAuth подтверждает, что у вас есть Gmail. Дiя подтверждает, что вы — это вы. Разница принципиальная: Дiя привязана к реальному документу — паспорту, ID-карте или квалифицированной электронной подписи.
Для юридической платформы, где адвокатская тайна и идентификация сторон — не опция, а требование закона, это единственно правильный уровень верификации.
Архитектура: два потока
Мобильный (deep link)
- Пользователь нажимает «Войти через Дiю»
- Бэкенд генерирует
requestId(ECDSA + SHA256, base64) - Открывается deep link
diia://с параметрами сессии - Приложение Дiя показывает запрос на авторизацию
- Пользователь подтверждает → Дiя отправляет callback с данными
- Бэкенд верифицирует подпись, создаёт JWT-сессию
Десктоп (QR-код)
- Бэкенд запрашивает сессию у Дiя API (
api2s.diia.gov.ua) - Получает deep link → конвертирует в QR-код
- Пользователь сканирует QR приложением Дiя на телефоне
- Далее — тот же поток: подтверждение → callback → JWT
Криптография: почему ECDSA
API Дiя требует хеширования requestId через ECDSA с SHA256. Не HMAC, не RSA — именно ECDSA. Это стандарт электронной подписи в Украине (ДСТУ 4145), и Дiя следует ему.
requestId = base64(ECDSA_SHA256(branchId + offerId + requestId))
Каждый запрос уникален. Каждая подпись верифицирована. Replay-атаки невозможны.
Что получаем от Дiя
После успешной авторизации:
| Поле | Описание |
|---|---|
| ФИО | Фамилия, имя, отчество |
| Дата рождения | Из документа |
| ИНН | Индивидуальный налоговый номер |
| Серия/номер документа | Паспорт или ID-карта |
| Фото | Из документа (опционально) |
Этого достаточно для полной идентификации на юридической платформе — и для будущей интеграции с ЕРАУ (верификация адвоката по ИНН).
Безопасность
- Данные не хранятся на стороне Дiя — после передачи callback сессия уничтожается
- Токен сессии одноразовый — повторное использование невозможно
- JWT с коротким TTL — 24 часа, refresh через повторную авторизацию
- Basic Auth для API — коммуникация бэкенд ↔ Дiя защищена отдельными credentials
UX: один тап вместо формы
На мобильном:
- Нажал «Войти через Дiю» → открылось приложение → подтвердил → вернулся в LEX AI авторизованным
На десктопе:
- Увидел QR-код → навёл камеру → подтвердил в приложении → страница автоматически обновилась
Никаких паролей. Никаких форм регистрации. Никаких «подтвердите email». То же приложение, которым вы показываете права на блокпосте — теперь ваш ключ к юридическому AI.
Три метода авторизации
LEX AI теперь поддерживает три независимых метода входа:
| Метод | Уровень доверия | Лучше всего для |
|---|---|---|
| Google OAuth | Базовый | Быстрый старт, ознакомление |
| Authentik SSO | Корпоративный | Юридические фирмы, организации |
| Дiя | Государственный | Полная идентификация, адвокаты |
Юрист выбирает свой уровень. Платформа адаптируется.
Production post-mortem: Redis + nginx
После деплоя на продакшн за AWS Application Load Balancer авторизация через Дiю перестала работать. Полностью. Пользователи нажимали «Войти через Дiю» — и получали ошибку.
Причин оказалось две, и обе — инфраструктурные.
Первая: расхождение ключей в Redis. При инициации сессии Дiя мы записывали стейт с одним префиксом, а при обратном вызове читали с другим. Redis молча возвращал null, бэкенд считал сессию невалидной и отклонял callback. Фикс — унификация префиксов ключей в одном месте.
Вторая: nginx перезаписывал X-Forwarded-Proto. ALB корректно передавал https, но nginx в своей конфигурации принудительно ставил http. Callback URL формировался с HTTP-схемой, Дiя отклоняла его как несоответствующий зарегистрированному redirect URI. Решение — nginx теперь пропускает оригинальный заголовок от балансера, а не подставляет свой.
Обе проблемы не воспроизводились локально, потому что в dev-среде нет ALB и Redis-префиксы совпадали случайно. Это напоминание: staging должен максимально повторять продакшн.