
ЕСИА даёт возможность пользователям зайти в государственный или негосударственный сервис, чтобы подать заявление, сдать отчет или обратиться в органы власти. ГИС ЖКХ, Работа России, портал ФНС России, ЦИАН и Авто.ру — этот список ежегодно пополняется. Для успешного подключения к системе важно соблюдать определенные требования и следовать установленным этапам интеграции.
В этой статье мы рассмотрим основные организационные аспекты подключения информационных систем к ЕСИА, а также один из вариантов его реализации.
Новые требования ЕСИА
С 2025 года вступает в силу новый регламент взаимодействия к ЕСИА (версия 2.47) и методические рекомендации (версия 3.48), которые вводят ряд новых требований по безопасности для инфраструктуры и ПО. Новые требования обязательны для всех новых подключений с 2025 года, а для уже работающих с ЕСИА организаций — с конца 2026 года.
Основные изменения:
-
Требуется использование сертифицированных средства криптографической защиты информации (СКЗИ) класса КС3.
-
Подключаемая информационная система должна пройти аттестацию по требованиям информационной безопасности (ИБ).
-
Взаимодействие с ЕСИА будет осуществляться через шлюзовой модуль (API Gateway), доступный с 2025 года.
-
С 31 декабря 2026 года необходимо реализовать поддержку OpenID Connect с подтверждением соответствия требованиям ФСБ (пройти оценку влияния на СКЗИ).
-
С 1 июля 2025 года для автоматического создания электронных подписей в ЕСИА необходим квалифицированный сертификат только на юридическое лицо (обезличенная ЭП).
Требования касаются четырех ключевых направлений:
-
Использование средств криптографической защиты — сертифицированные ФСБ или ФСТЭК СКЗИ, соответствие уровню доверия не ниже 5, защищенные каналы связи класса не ниже KC3.
-
Безопасность подключаемых информационных систем — соответствие уровню защищенности персональных данных УЗ.3 и выше, аттестация и использование сертифицированных средств защиты информации (СЗИ).
-
Реализация взаимодействия с ЕСИА — проверка реализации OpenID Connect и оценка влияния на СКЗИ.
-
Организационные меры — выполнение требований ЦБ к обеспечению защиты информации (для кредитных организаций), сертифицированный антивирус, размещение серверов на территории РФ.
Как подключиться к ЕСИА
Основные этапы подключения следующие:
-
Регистрация ресурса в ЕСИА
Владелец информационной системы обязан зарегистрировать ее в технологическом портале ЕСИА. Для этого должна быть учетная запись юридического лица на портале Госуслуг, подтвержденная квалифицированной электронной подписью.
-
Получение закрытого ключа и сертификата открытого ключа для подписи запросов
Для идентификации системы в ЕСИА создаются закрытый ключ и сертификат открытого ключа, которые затем используются при подключении к тестовой и боевой среде.
-
Тестирование в песочнице
В тестовой среде проводится проверка корректности работы программного обеспечения, взаимодействующего с ЕСИА. Вы можете использовать готовое решение, так и разработать его самостоятельно.
-
Заявка на подключение к промышленной среде
После успешного тестирования направляется заявка на подключение к боевой среде ЕСИА.
Технические аспекты интеграции
Тема интеграции с ЕСИА неоднократно обсуждалась на habr, поэтому мы рассмотрим только основные ключевые моменты.
Основные этапы процесса обмена данными между системой и ЕСИА отображены на этой диаграмме последовательности:

Все технические нюансы интеграции детально описаны в Методических рекомендациях по использованию ЕСИА. Этот документ объемом 511 страниц содержит примеры кода и сценарии использования механизмов SSO на основе SAML 2.0 и OpenID Connect 1.0.
Реализация OpenID Connect / OAuth 2.0 в ЕСИА в целом основана на спецификациях RFC6749 и OpenID Connect 1.0. Но есть моменты, на которые стоит обратить внимание.
Основные отличия OpenID Connect 1.0 в ЕСИА:
-
client_secret в виде электронной подписи — вместо обычной секретной строки используется электронная подпись, особенности ее формирования описаны в Методических рекомендациях.
-
Ограниченные grant types — поддерживаются только Authorization Code Flow и Client Credentials Flow.
-
Отсутствие стандартного UserInfo Endpoint — вместо него используются специфичные REST API ЕСИА.
-
Собственный справочник scope — стандартные OpenID Connect scopes не поддерживаются.
-
Ограниченная поддержка опциональных режимов — доступны display=page/popup и prompt=none/login, но большинство других опций OpenID Connect отсутствуют.
-
Стандартные OIDC/OAuth 2.0 библиотеки требуют доработки — из-за особенностей ЕСИА их нельзя использовать без модификаций.
Получение тестового сертификата
Для подключения к ЕСИА будем использовать тестовый сертификат, полученный в личном кабинете участника взаимодействия (ЛК УВ)
Генерация тестового сертификата для взаимодействия в тестовой среде (в среде разработки):

На последнем шаге добавления информационной системы мы получим сертификат, закрытый ключ и пароль. В скачанном zip-архиве будут данные в таком виде:
├── certs — папка с сертификатами ├── s059negs.cer — файл сертификата └── cp_ca_store — хранилище доверенных сертификатов в формате CryptoPro └── keys — папка с ключами ├── header.key ├── masks2.key ├── masks.key ├── name.key ├── primary2.key └── primary.key
Загружаем полученный сертификат в технологическом портале тестовой среды ЕСИА.

Экспортируем закрытый ключ, получаем файл s059negs.pfx. Он будет использоваться в дальнейшем для формирования подписи запросов.

Формирование client_secret
Согласно Методическим рекомендациям для формирования ссылки для получения авторизационного кода client_secret должен содержать отсоединенную подпись запроса в формате PKCS#7 в кодировке UTF-8 от значений четырех параметров: scope, timestamp, clientId, state (без разделителей) и должен быть закодирован в формате base64 url safe.
ЕСИА использует сертификаты в формате X.509 и взаимодействует с алгоритмами формирования электронной подписи ГОСТ Р 34.10-2012 и криптографического хеширования ГОСТ Р 34.11-2012. Используемый для проверки подписи сертификат должен быть предварительно зарегистрирован в ЕСИА и привязан к учетной записи системы клиента в ЕСИА.
Все, что связано с криптографическими операциями подписи запросов и ее проверки, может быть реализовано в отдельном сервисе, что позволяет легко его интегрировать в любые существующие решения.

Загружаем полученный ранее файл s059negs.pfx в сервис подписи:
docker exec -it cryptoarm.server /opt/cprocsp/bin/amd64/certmgr -inst -all -store uMy -file /certs/s059negs.pfx -pfx -pin we2ofzhr

Готовим client_secret. Текст запроса:
openid fullname email gender mobile birthdate birthplace addresses inn snils id_doc2025.02.13 20:00:21 +030077A8031c506312-cb28-447d-8ec9-68144d698acc
Заворачиваем сертификат подписи и текст запроса в Base64 и отправляем в сервис подписи:

Помещаем полученную подпись в client_secret и получаем ссылку такого вида:
https://esia-portal1.test.gosuslugi.ru/aas/oauth2/ac?redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fapi%2Fesia%2Fcode&response_type=code&access_type=offline&state=8031c506312-cb28-447d-8ec9-68144d698acc×tamp=2025.02.13+20%3A00%3A21+%2B0300&client_id=XXXXX&scope=openid+fullname+email+gender+mobile+birthdate+birthplace+addresses+inn+snils+id_doc&client_secret=MIAGCSqGSIb3DQEHAqCAMIACAQ…
Примеры реализации (Nest.js):
@Injectable() export class EsiaService { /** * Формирование ссылки для получения авторизационного кода */ async getAuthLink(provider: TEsiaProvider) { const signParams = await this.signParams( { redirect_uri: provider.params.redirect_uri, response_type: 'code', access_type: 'offline', }, provider.params, ); const authQuery = new URLSearchParams(signParams); return `${provider.params.authorization_endpoint}?${authQuery}`; } /** * Отправляет запрос на signUrl для получения ГОСТ подписи */ async signText(text: string, signUrl: string, password: string) { try { const data = Buffer.from(text).toString('base64'); const response = await fetch(signUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ data, password }), }); const { sign } = await response.json(); return sign; } catch (e) { throw new BadRequestException('signText', 'Не удалось подписать контент'); } } /** * Формирование подписанных ГОСТом параметров для отправки */ private async signParams(params: Record<string, string>, esiaParams: TEsiaParams) { const time = moment().format('YYYY.MM.DD HH:mm:ss ZZ'); const state = uuid(); const scope = esiaParams.scopes; const client_secret = await this.signText( [scope, time, esiaParams.external_client_id, state].join(''), esiaParams.sign_endpoint, ); return { ...params, timestamp: time, client_id: esiaParams.external_client_id, scope, state, client_secret, }; }
Теперь направляем пользователя по данной ссылке и ждем, пока он пройдет авторизацию. После этого ЕСИА перенаправит его на указанный в redirect_uri адрес, передав авторизационный код и state.
Получение маркера доступа
После получения авторизационного кода клиентская система отправляет запрос на endpoint ЕСИА для получения маркера доступа. Один авторизационный код можно использовать для получения только одного маркера доступа. В теле запроса, помимо всех параметров, указанных при запросе авторизационного кода, необходимо включить следующие данные:
-
code — значение авторизационного кода
-
grant_type — «authorization_code»
-
state — должен отличаться от того, который использовался при получении авторизационного кода
-
redirect_uri — может быть «no»
-
token_type — «Bearer»
/** * Получение токенов по коду */ async getTokens(code: string, provider: TEsiaProvider) { const params = await this.signParams( { grant_type: 'authorization_code', token_type: 'Bearer', redirect_uri: 'no', code, }, provider.params, ); const authQuery = new URLSearchParams(params); const response = await fetch(provider.params.token_endpoint, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: authQuery, }); if (!response.ok) throw new BadRequestException('getTokens', 'Не удалось получить токены'); const tokens = await response.json(); return { idToken: tokens.id_token, accessToken: tokens.access_token, refreshToken: tokens.refresh_token, }; }
Если запрос успешно прошел проверку, то ЕСИА возвращает маркеры доступа (токены), позволяющие получать доступ к данным пользователя:
{ "access_token": "eyJ2ZXIiOjEsInR5cCI6IkpXVCIsInNidCI6ImFjY2VzcyIsImFs...", "refresh_token": "0f9362d1-d07c-4ba5-92b6-213d466e60e9", "id_token": "eyJ2ZXIiOjAsInR5cCI6IkpXVCIsInNidCI6ImlkIiwiYWxnIjoiR09T...", "state": "a9983c07-ec98-4a7c-ab68-c9efd1b2105c", "token_type": "Bearer", "expires_in": 3600 }
Содержимое id_token:

Из id_token получаем sub — идентификатор конечного пользователя.
Получение данных пользователя
С помощью accessToken и sub мы уже можем получить персональные данные пользователя.
/** * Получение информации о пользователе */ async getUserInfo(accessToken: string, sub: string, provider: TEsiaProvider) { const endpoint = provider.params.esia_endpoint; const headers = { Authorization: `Bearer $ accessToken}` }; const [main, contacts, docs] = await Promise.all([ fetch(`${endpoint}/${sub}`, { headers }).then((response) => response.json() ), fetch(`${endpoint}/${sub}/ctts?embed=(elements)`, { headers }).then( (response) => response.json() ), fetch(`${endpoint}/${sub}/docs?embed=(elements)`, { headers }).then( (response) => response.json() ), ]); /** * main - данные о пользователе * contacts - контактные данные пользователя * docs - документы пользователя */ return { main, contacts, docs }; }
Заключение
Интеграция с ЕСИА предоставляет эффективный инструмент для повышения безопасности и удобства аутентификации пользователей.
Мы рассмотрели новые требования, основные этапы подключения, технические особенности интеграции и привели пример её реализации.
Надеемся, что представленные материалы окажутся полезными и помогут вам успешно внедрить интеграцию с ЕСИА в ваших проектах.
Ссылки:
ссылка на оригинал статьи https://habr.com/ru/articles/893544/
Добавить комментарий