Инструкция по работе с тестовой средой есиа

Время на прочтение
6 мин

Количество просмотров 12K

Привет, Хабр! В одном из постов блога мой коллега Иван писал о нашем блокчейн-сервисе для онлайн-голосований WE.Vote. Он подробно разобрал, как работает WE.Vote с точки зрения технологий. Но чтобы сервисы удаленного голосования можно было использовать для принятия официальных решений юрлиц, не хватает еще одного важного компонента — достоверной верификации участников. В России для этого можно провести интеграцию с ЕСИА (Единой Системой Идентификации и Аутентификации) — проще говоря, с Госуслугами. Интеграция эта заметно отличается от интеграции с другими OAuth2-сервисами, как, например, Google или VK. В этом посте мы постараемся помочь тем, кто захочет интегрировать ЕСИА в свой сервис через стек, подобный нашему, а также дадим несколько полезных ссылок по ЕСИА в принципе.

Зачем нам ЕСИА?

Согласно Федеральному закону № 225-ФЗ от 28.06.2021 «О внесении изменений в часть первую Гражданского кодекса Российской Федерации», многие организаций в РФ получили право проводить официальные собрания и голосования по корпоративным вопросам дистанционно.

Ранее решения с юридической силой требовали очных собраний или голосований по почте. Голосования по почте не отличаются надежностью, а собрать много руководителей со всей России в одном месте — это кошмар с точки зрения затрат.

Чтобы проводить мероприятия принятия решения дистанционно в соответствии с новым федеральным законом, необходимо предоставить возможность достоверного установления личности участников. В России это возможно через проверку доступа к верифицированному аккаунту на Госуслугах.

Стек и схема интеграции

Для интеграции мы используем:

  • Typescript, ReactJS, NestJS

  • КриптоПро CSP 4

  • Docker, Kubernetes

Схема интеграции

Схема интеграции

Формирование подписи

Прежде чем разбирать все по порядку, кое о чем стоит подумать заранее. В отличие от других интеграций, запросы к ЕСИА должны сопровождаться подписью ГОСТ Р 34.10/11-2012, а не просто API key. Создать такую подпись можно с помощью утилиты КриптоПро CSP. Для нас основная задача здесь — правильно обернуть эту утилиту в Docker, чтобы с ней можно было работать как с отдельным сервисом в рамках нашей инфраструктуры. Получившийся сервис мы выложили в открытый доступ на гитхабе. Инструкция по запуску есть в README.md.

В процесс сборки Docker образа сервиса с утилитой КриптоПро мы встроили:

  • Установку утилиты КриптоПро СSP 4 из .deb пакета

  • Установку лицензии КриптоПро

  • Загрузку корневого сертификата тестовой или основной среды ЕСИА

  • Загрузку пользовательского сертификата с PIN кодом

  • REST-сервер с методом, позволяющим создавать подписи

Таким образом вся криптография собрана в отдельном самостоятельном компоненте, который можно использовать, когда необходимо что-нибудь подписать. Вот как это выглядит на бэкенде:

private async signParams(params: Record<string, string>) {
 const time = moment().format('YYYY.MM.DD HH:mm:ss ZZ')
 const state = uuid()
 const clientId = this.clientId
 const scope = this.scope

 const { data: { result: clientSecret } } = await axios.post<{ result: string }>(
   `${this.cryptoProServiceAddress}/cryptopro/sign`,
   { text: [scope, time, clientId, state].join('') },
 )

 return {
   ...params,
   timestamp: time,
   client_id: clientId,
   scope,
   state,
   client_secret: clientSecret.replace(/n/g, ''),
 }
}

С созданием подписей разобрались, теперь последовательно разберем, как реализовать схему выше.

Создание ссылки для редиректа на страницу ЕСИА

Все начинается с того, что пользователь решает пройти авторизацию через ЕСИА. Создаем на бэкенде ссылку для перехода с использованием нашего инструмента формирования подписей.

async getAuthLink(redirectLink: string) {
 const params = await this.signParams({
   redirect_uri: redirectLink,
   response_type: 'code',
   access_type: 'offline',
 })
 const authQuery = new URLSearchParams(params)
 const authURL = `${this.esiaHost}/aas/oauth2/ac`
 return `${authURL}?${authQuery}`
}

В redirectLink необходимо указать адрес страницы, на которую ЕСИА перенаправит пользователя после успешной аутентификации. Созданную ссылку возвращаем на фронтенд и перенаправляем на нее пользователя.

Получение авторизационного токена ЕСИА

Запрос токена идентификации

После успешной аутентификации на странице ЕСИА пользователь возвращается на фронтенд приложения по указанному нами адресу. ЕСИА передаёт авторизационный токен в виде get-параметра code. Этот токен необходимо передать на бэкенд и запросить с его помощью идентификационный токен пользователя.

async getTokens(code: string) {
 try {
   const params = await this.signParams({
     grant_type: 'authorization_code',
     token_type: 'Bearer',
     redirect_uri: 'no',
     code,
   })
   const authURL = `${this.host}/aas/oauth2/te`
   const authQuery = new URLSearchParams(params)
   const { data: tokens } = await axios.post(`${authURL}?${authQuery}`)
   return {
     idToken: tokens.id_token,
     accessToken: tokens.access_token,
     refreshToken: tokens.refresh_token,
   }
 } catch (e) {
   const status = e.response ? e.response.status : 500
   const message = e.response ? e.response.data.error_description : e.message
   throw new HttpException('Failed to get auth tokens: ' + message, status)
 }
}

Получение данных о пользователе

Идентификационный токен пользователя необходимо проверить с помощью публичного RSA ключа от ЕСИА и получить из него id пользователя. С помощью этого id и accessToken, который мы получили в предыдущем шаге, мы уже наконец можем запросить персональные данные пользователя.

getUserIdFromToken(idToken: string) {
 const decodedIdToken = verify(idToken, this.esiaPublicKey, {
   algorithms: ['RS256'],
   audience: 'WE_VOTE',
 }) as EsiaParsedToken
 return decodedIdToken['urn:esia:sbj']['urn:esia:sbj:oid']
}

async getUserInfo(tokens: EsiaTokens) {

 const { idToken, accessToken } = tokens
 const oId = this.getUserIdFromToken(idToken)

 const [{ data: mainInfo }, { data: contactsInfo }] = await Promise.all([
   axios.get(`${this.esiaHost}/rs/prns/${oId}`, {
     headers: {
       Authorization: `Bearer ${accessToken}`,
     },
   }),
   axios.get(`${this.esiaHost}/rs/prns/${oId}/ctts?embed=(elements)`, {
     headers: {
       Authorization: `Bearer ${accessToken}`,
     },
   }),
 ])

 const email = contactsInfo.elements.find(({ type }: { type: string }) => type === 'EML')

 return {
   id: oId,
   firstName: mainInfo.firstName,
   lastName: mainInfo.lastName,
   surName: mainInfo.middleName,
   trusted: mainInfo.trusted,
   email: email ? {
     value: email.value.toLowerCase(),
     verified: email.vrfStu === 'VERIFIED',
   } : null,
 }
}

На этом шаге мы уже имеем все необходимые данные о пользователе. Остается только занести их в свою систему и закончить авторизацию.

Полный код интеграционного модуля на бэкенде

import { HttpException } from '@nestjs/common'
import * as moment from 'moment'
import { v4 as uuid } from 'uuid'
import { URLSearchParams } from 'url'
import axios from 'axios'
import { verify } from 'jsonwebtoken'

type EsiaTokens = {
 idToken: string,
 accessToken: string,
}

type EsiaParsedToken = {
 'urn:esia:sbj': {
   'urn:esia:sbj:oid': string,
 },
}

export class EsiaApiService {
 private readonly clientId = 'WE_VOTE'
 private readonly scope = ['openid', 'email', 'fullname'].join(' ')

 constructor(
   private readonly esiaHost: string, // 'https://esia-portal1.test.gosuslugi.ru' или 'https://esia.gosuslugi.ru'
   private readonly esiaPublicKey: string, // можно взять из http://esia.gosuslugi.ru/public/esia.zip
   private readonly cryptoProServiceAddress: string, // адрес сервиса по созданию подписей e.g 'http://127.0.0.1:3037'
 ) {
 }

 async getAuthLink(redirectLink: string) {
   const params = await this.signParams({
     redirect_uri: redirectLink,
     response_type: 'code',
     access_type: 'offline',
   })
   const authQuery = new URLSearchParams(params)
   const authURL = `${this.esiaHost}/aas/oauth2/ac`
   return `${authURL}?${authQuery}`
 }

 private async signParams(params: Record<string, string>) {
   const time = moment().format('YYYY.MM.DD HH:mm:ss ZZ')
   const state = uuid()
   const clientId = this.clientId
   const scope = this.scope

   const { data: { result: clientSecret } } = await axios.post<{ result: string }>(
     `${this.cryptoProServiceAddress}/cryptopro/sign`,
     { text: [scope, time, clientId, state].join('') },
   )

   return {
     ...params,
     timestamp: time,
     client_id: clientId,
     scope,
     state,
     client_secret: clientSecret.replace(/n/g, ''),
   }
 }

 async getTokens(code: string) {
   try {
     const params = await this.signParams({
       grant_type: 'authorization_code',
       token_type: 'Bearer',
       redirect_uri: 'no',
       code,
     })
     const authURL = `${this.esiaHost}/aas/oauth2/te`
     const authQuery = new URLSearchParams(params)
     const { data: tokens } = await axios.post(`${authURL}?${authQuery}`)
     return {
       idToken: tokens.id_token,
       accessToken: tokens.access_token,
       refreshToken: tokens.refresh_token,
     }
   } catch (e) {
     const status = e.response ? e.response.status : 500
     const message = e.response ? e.response.data.error_description : e.message
     throw new HttpException('Failed to get auth tokens: ' + message, status)
   }
 }

 getUserIdFromToken(idToken: string) {
   const decodedIdToken = verify(idToken, this.esiaPublicKey, {
     algorithms: ['RS256'],
     audience: this.clientId,
   }) as EsiaParsedToken
   return decodedIdToken['urn:esia:sbj']['urn:esia:sbj:oid']
 }

 async getUserInfo(tokens: EsiaTokens) {

   const { idToken, accessToken } = tokens
   const oId = this.getUserIdFromToken(idToken)

   const [{ data: mainInfo }, { data: contactsInfo }] = await Promise.all([
     axios.get(`${this.esiaHost}/rs/prns/${oId}`, {
       headers: {
         Authorization: `Bearer ${accessToken}`,
       },
     }),
     axios.get(`${this.esiaHost}/rs/prns/${oId}/ctts?embed=(elements)`, {
       headers: {
         Authorization: `Bearer ${accessToken}`,
       },
     }),
   ])

   const email = contactsInfo.elements.find(({ type }: { type: string }) => type === 'EML')

   return {
     id: oId,
     firstName: mainInfo.firstName,
     lastName: mainInfo.lastName,
     surName: mainInfo.middleName,
     trusted: mainInfo.trusted,
     email: email ? {
       value: email.value.toLowerCase(),
       verified: email.vrfStu === 'VERIFIED',
     } : null,
   }
 }

}

Надеюсь, статья оказалась для вас полезной. Желаю, чтобы у вас все получилось без особых проблем! 

Полезные материалы по теме

  • Наш сервис по созданию подписей с использованием КриптоПро 

  • MVP-проект с Криптопро в докере

  • Методические указания по интеграции от ЕСИА

  • Инструкция по работе с тестовой средой ЕСИА

  • КриптоПро CSP

  • Интеграция на Java

  • Второй вариант интеграции на Java

  • Описание процесса OAuth2-интеграции

Единая система идентификации и авторизации (ЕСИА) – это единственный способ верифицировать личность пользователя. Если продукт работает с деньгами, решает юридические задачи или работает с медицинскими данными, без интеграции с ЕСИА не обойтись. Рассказываем, что нужно знать, чтобы работать с этой инфраструктурой.

ЕСИА появилась в 2010 году и изначально использовалась для авторизации на Портале госуслуг. За прошедшее время возможности системы постоянно развивались, и сегодня коммерческие организации используют её, чтобы связывать учётные записи пользователя с их оффлайн-личностью.

То есть если компании нужно удостовериться, что по ту сторону экрана действительно тот человек, которым представился пользователь, ЕСИА предоставляет такую возможность. И самое главное – эта идентификация имеет юридическую значимость.

Какие возможности открывает такая идентификация

1. Клиент может подписывать юридически значимые электронные документы, получать защищённый доступ к конфиденциальной информации, медицинским данным и т.д.

2. Появляется возможность автоматически заполнять в анкетах и заявках персональные данные клиента: ФИО, данные паспорта, ИНН, информация о детях и др. При этом компания может быть уверена, что эти данные абсолютно верны и правдивы.

3. Страховые компании и банки могут продавать через приложение свои продукты. И никаких расходов, которые связаны с традиционными, оффлайновыми каналами продаж – не нужно собирать документы, приглашать человека в офис, достаточно разработать скрипт для колл-центра.

4. Для пользователя верификация с ЕСИА повышает доверие к сервису и делает саму процедуру удобнее – не нужно помнить дополнительные пароли, просто нажимаешь знакомую кнопку и всё.

В наших проектах интеграция ЕСИА активно используется в продуктах страховых компаний. Это позволяет клиентам покупать полисы ОСАГО, отправлять извещения о ДТП при оформлении заявок на урегулирование убытков. Это критически важная функция для сценариев заявления о страховых случаях по ОСАГО, когда пользователь не является клиентом данной страховой компании.

Хотя сейчас к ЕСИА могут подключиться не все организации, можно ожидать, что такая авторизация скоро станет де-факто стандартом для пользовательских сервисов. Просто потому, что это надёжно и удобно для клиентов – вместо отдельной учётной записи для каждого ресурса можно использовать единый аккаунт «Госуслуг» и бесшовно пользоваться любыми нужными услугами. Поэтому задумываться об интеграции стоит всем компаниям.

Как информационная система работает с ЕСИА

ЕСИА является прослойкой между стандартным содержанием приложения и его защищёнными данными. Если пользователю не требуются услуги, которые требуют верификации личности, он может не проходить дополнительную авторизацию. Когда же он захочет попасть в этот раздел, приложение переадресует его на Портал госуслуг, а после успешной авторизации – вернёт обратно.

Технически процесс выглядит так:

1. Пользователь обращается к защищённому ресурсу информационной системы (например, при онлайн-покупке полиса ОСАГО).

2. Информационная система направляет в ЕСИА запрос на аутентификацию.

3. ЕСИА проверяет, есть ли у пользователя открытая сессия, т.е. авторизовался ли он уже ранее. Если такой сессии нет, ЕСИА направляет пользователя на веб-страницу, чтобы он ввёл свой логин и пароль.

4. После успешной аутентификации ЕСИА передаёт в информационную систему пакет с идентификационными данными пользователя, информацию об уровне его учётной записи и контексте аутентификации.

5. На основании этой информации система открывает пользователю доступ.

Как организации подключиться к ЕСИА

Процедура подключения занимает около месяца. Это время включает регистрацию необходимых аккаунтов, получение данных от Минцифры, работы по интеграции ИС.

1. Зарегистрируйте руководителя организации на Портале госуслуг. Регистрировать компании в ЕСИА могут только те их представители, которые вправе действовать без доверенности. Им понадобится подтверждённая учётная запись физического лица – т.е. нужно будет не только указать свои данные, но и обратиться в банк или МФЦ для верификации. В последнее время многие банки позволяют сделать это онлайн, через их приложения.

2. Зарегистрируйте вашу организацию.

a. Получите квалифицированную электронную подпись (КЭП) на руководителя организации.

b. Зарегистрируйте юридическое лицо в профиле ЕСИА.

c. Оформите КЭП для юридического лица.

Оформлением КЭП занимаются аккредитованные удостоверяющие центры. Подробная инструкция по этому процессу здесь.

3. Зарегистрируйте информационную систему в ЕСИА.

Регистрация системы происходит через технологический портал. Доступ к нему может получить один из сотрудников компании – действовать через аккаунт представителя уже не обязательно. Этот процесс подробно расписан в Руководстве пользователя технологического портала ЕСИА. В результате регистрации информационная система заносится в реестр ИС и получает мнемонический буквенно-цифровой код.

4. Доработайте систему для обмена данными с ЕСИА.

Аутентификация пользователей в ЕСИА происходит по OAuth 2.0 и OpenID Connect 1.0. Компании необходимо сгенерировать закрытый ключ и сертификат открытого ключа, зарегистрировать его на технологическом портале. Стоит отметить, что ЕСИА поддерживает только российские алгоритмы шифрования ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012.

Стоит отдельно отметить, что если в компании уже используются средства верификации пользователей посредством Single Sign-On, то особых технических трудностей при подключении к ЕСИА не будет.

5. Подключитесь к тестовой среде ЕСИА

На этом этапе нужно отправить на адрес [email protected] заявку по форме, которая приводится в Регламенте взаимодействия заявителей с операторами ЕСИА. Когда администраторы откроют доступ, компании нужно подключить свою систему к ЕСИА, чтобы она могла принимать и отправлять запросы. Для этого используются специальные коннекторы, и Минцифры не даст разрешение на полноценный запуск, пока коннекторы не заработают стабильно в тестовом режиме.

6. Подключитесь к промышленной среде ЕСИА

Когда всё готово, вы отправляете ещё одну заявку на [email protected]. Остаётся проверить работоспособности интеграции – и готово.

Полезные ссылки

Данный документ описывает порядок регистрации портала записи пациента на прием к врачу, далее ИС (информационная система) в системе ЕСИА.

Применимо для регистрации других ИС с поправками на специфику.

Нормативные документы 

  • Руководство пользователя ЕСИА 
    https://digital.gov.ru/ru/documents/6182/ 
  • Руководство пользователя технологического портала ЕСИА 
    https://digital.gov.ru/ru/documents/6190/ 
  • Методические рекомендации по использованию ЕСИА 
    https://digital.gov.ru/ru/documents/6186/ 
  • Регламент информационного взаимодействия Участников с Оператором ЕСИА и оператором эксплуатации инфраструктуры электронного правительства 
    https://digital.gov.ru/ru/documents/4244/ 

Ресурсы:

Технологический портал (ПРОМЫШЛЕННАЯ СРЕДА): http://esia.gosuslugi.ru/console/tech 

Технологический портал (ТЕСТОВАЯ СРЕДА): https://esia-portal1.test.gosuslugi.ru/console/tech 

1) Зарегистрируйте вашу организацию в ЕСИА

Необходимо получить квалифицированную электронную подпись (КЭП) на руководителя организации и зарегистрировать юридическое лицо или орган государственной власти в профиле ЕСИА (п.3 Руководства пользователя ЕСИА). Вам потребуется КЭП юридического лица (в т.ч. это может быть подпись ЭП-СП). За получением средства КЭП нужно обратиться в один из аккредитованных Минкомсвязью России удостоверяющих центров вашего региона.

!

Если у вашей организации уже есть доступ к ЕСИА сразу перейти к п.2

2) Зарегистрируйте информационную систему в ЕСИА

Ответственном сотруднику необходимо предоставить доступ к технологическому порталу (п. 3.5.2.3 Руководства пользователя). В результате регистрации через технологический портал ваша информационная система заносится в реестр ИС, взаимодействующих с ЕСИА. Для ИС присваивается буквенно-цифровой код — мнемоника.

Сотрудник должен быть привязан к организации!

3) Сертификаты ИС

В ЕСИА создан механизм аутентификации пользователей, основанный на спецификациях OAuth 2.0 и расширении OpenID Connect 1.0.
Необходимо сгенерировать закрытый ключ и сертификат открытого ключа, зарегистрировать его в технологическом портале.
Подробно необходимые действия описаны в разделе 3.1. Методических рекомендаций.

ВАЖНО

С ноября 2019 года подключение ИС в ЕСИА осуществляется только с сертификатами, поддерживащими алгоритмы шифрования ГОСТ-2012. 

Портал записи на прием на данный момент работает только с ключами криптопровайдера  КриптоПРО. 

4) Подключитесь к тестовой среде ЕСИА

Необходимо отправить форму заявки на адрес sd@sc.minsvyaz.ru. Актуальная форма размещена в Регламенте взаимодействия — ПРИЛОЖЕНИЕ Е. ФОРМА ЗАЯВКИ НА СОГЛАСОВАНИЕ ПРАВА ИСПОЛЬЗОВАНИЯ ЕСИА И НА ПОДКЛЮЧЕНИЕ ИНФОРМАЦИОННОЙ СИСТЕМЫ К ЕСИА С ЦЕЛЬЮ ИСПОЛЬЗОВАНИЯ ПРОГРАММНЫХ ИНТЕРФЕЙСОВ ЕСИА ДЛЯ ИДЕНТИФИКАЦИИ И АУТЕНТИФИКАЦИИ ЗАЯВИТЕЛЕЙ

!

К заявке прилагаются файлы открытого (сертификата) и закрытого ключа в формате DER.

SCOPE

В заявке необходимо перечислить следующие SCOPE (типы запрашиваемых персональных данных гражданина)

Scope:
— openid
— fullname
— birthdate
— gender
— snils
— inn
— id_doc
— birthplace
— medical_doc
— drivers_licence_doc
— birth_cert_doc
— email
— mobile
— contacts
— usr_org
— kid_fullname
— kid_birthdate
— kid_gender
— kid_snils
— kid_inn
— kid_birth_cert_doc
— kid_medical_doc

Пример заполнения заявки: 

После получения доступа в тестовую среду необходимо произвести настройку сервиса подписи на портале. 

Для этого понадобится: 

  • сертификат в формате DER
  • пароль от сертификата
  • контейнер закрытых ключей
  • лицензионный ключ КриптоПРО

Данные ключи необходимо передать ответственному сотруднику СТП. Или настроить сервис подписи самостоятельно.

После настройки и проверки тестовой среды можно переходить к регистрации в промышленной среде.

5) Подключитесь к промышленной среде ЕСИА

Необходимо отправить форму заявки на адрес sd@sc.minsvyaz.ru. Форма заявки как при подключении к тестовой среде.

Проверить наличие ИС на технологическом портале ПРОМЫШЛЕННОЙ СРЕДЫ, а так же наличие и актуальность прикрепленных там сертификатов.

После получения доступа в промышленную среду, необходимо настроить сервис подписи портала для подписи запросов в ЕСИА. 

Для этого понадобится: 

  • сертификат в формате DER
  • пароль от сертификата
  • контейнер закрытых ключей
  • лицензионный ключ КриптоПРО

Данные ключи необходимо передать ответственному сотруднику СТП. Или настроить сервис подписи самостоятельно.

Проверить работоспособность портала — авторизоваться на портале записи на прием под учетной записью реального гражданина.

6) Доменные имена

Согласно ФЗ №8 «ОБ ОБЕСПЕЧЕНИИ ДОСТУПА К ИНФОРМАЦИИ О ДЕЯТЕЛЬНОСТИ ГОСУДАРСТВЕННЫХ ОРГАНОВ И ОРГАНОВ МЕСТНОГО САМОУПРАВЛЕНИЯ» информационные ресурсы (сайты) принадлежащие государственным или муниципальным организациям должны располагаться на доменах принадлежащих этим организациям. 

В связи с этим МИАЦ региона должен зарегистрировать доменное имя любого уровня для портала записи пациентов, а так же обеспечить доступ к сайту по защищенному протоколу HTTPS, для чего потребуется https сертификат.  

Cертификаты SSL (HTTPS)

Текущие доменные имена вида код_региона.2dr.ru остаются в рабочем состоянии как резервные. 


Offline

Ludmila Tihonova

 


#1
Оставлено
:

15 мая 2022 г. 14:14:42(UTC)

Ludmila Tihonova

Статус: Advanced Member

Группы: Registered

Зарегистрирован: 29.07.2018(UTC)
Сообщений: 663

Сказал(а) «Спасибо»: 41 раз
Поблагодарили: 35 раз в 34 постах

Начинается поэтапное тестирование функционала суперсервиса с использованием тестового ЕПГУ (тестовый кабинет госуслуг).

Презентация для вузов: Prezentacija SS PVO_05052022.pdf (1,898kb) загружен 13 раз(а).

Для тестирования необходимо выполнить следующие условия:

1. Убедиться в наличии подключения к Сервису приема.
2. Внести в тестовый Сервис приема правила приема, необходимые для тестирования, в том числе по филиалам, а именно: по конкурсным группам и направлениям подготовки, количеству доступных для выбора направлений, информацию о наличии общежития, ВУЦ, формах обучения, уровнях образования, предметах вступительных испытаний и минимальных баллы к ним. Проверить корректность внесенных данных.
3. Перевести приемную кампанию в статус «Идет набор». После перевода статуса ПК нужно подождать пока синхронизируются данные (15-20 минут).
4. Получить тестовую учетную запись в ЕСИА, предназначенную для вашего вуза. Дополнительно (при желании) вы можете самостоятельно завести необходимое количество учетных записей в тестовой ЕСИА. Актуальное руководство пользователя ЕСИА опубликовано по адресу: https://digital.gov.ru/ru/documents/6182/
5. Авторизовавшись с использованием тестовой учетной записи ЕСИА, перейти к форме на ЕПГУ в тестовом контуре.
6. Приступить к тестированию.

7. Функционал тестированию на данном этапе:
а) выбор вуза;
б) проверка корректности отображения направлений подготовки, конкурсных групп и сопутствующей информации по ним.

8. Цель проведения тестирования: проверка полноты и корректности отображения данных, внесённых в тестовый Сервис приёма.


Вверх
Пользователи, просматривающие эту тему

Гость

Быстрый переход
 

Вы не можете создавать новые темы в этом форуме.

Вы не можете отвечать в этом форуме.

Вы не можете удалять Ваши сообщения в этом форуме.

Вы не можете редактировать Ваши сообщения в этом форуме.

Вы не можете создавать опросы в этом форуме.

Вы не можете голосовать в этом форуме.

Как и обещал
Предварительные условия
Для работы требуется наличие публичного и приватного ключа в соответствии с методическими рекомендациями по работе с ЕСИА. Допускается использование самоподписного сертифката, который можно сгенерировать следующей командой:

openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -sha1 -keyout my_private.key -out my_public_cert.crt
Полученный в результате файл my_public_cert.crt должен быть привязан к информационной системе вашей организации на сайте Госуслуг, а также направлен вместе с заявкой на доступ к ЕСИА (подробнее см. документы http://minsvyaz.ru/ru/documents/?words=ЕСИА).

Для валидации ответов от ЕСИА потребуется публичный ключ, который можно запросить в технической поддержке ЕСИА, уже после регистрации информационной системы и получения доступа к тестовой среде ЕСИА. Валидация опциональна.

Время на прочтение
6 мин

Количество просмотров 19K

Привет, Хабр! В одном из постов блога мой коллега Иван писал о нашем блокчейн-сервисе для онлайн-голосований WE.Vote. Он подробно разобрал, как работает WE.Vote с точки зрения технологий. Но чтобы сервисы удаленного голосования можно было использовать для принятия официальных решений юрлиц, не хватает еще одного важного компонента — достоверной верификации участников. В России для этого можно провести интеграцию с ЕСИА (Единой Системой Идентификации и Аутентификации) — проще говоря, с Госуслугами. Интеграция эта заметно отличается от интеграции с другими OAuth2-сервисами, как, например, Google или VK. В этом посте мы постараемся помочь тем, кто захочет интегрировать ЕСИА в свой сервис через стек, подобный нашему, а также дадим несколько полезных ссылок по ЕСИА в принципе.

Зачем нам ЕСИА?

Согласно Федеральному закону № 225-ФЗ от 28.06.2021 «О внесении изменений в часть первую Гражданского кодекса Российской Федерации», многие организаций в РФ получили право проводить официальные собрания и голосования по корпоративным вопросам дистанционно.

Ранее решения с юридической силой требовали очных собраний или голосований по почте. Голосования по почте не отличаются надежностью, а собрать много руководителей со всей России в одном месте — это кошмар с точки зрения затрат.

Чтобы проводить мероприятия принятия решения дистанционно в соответствии с новым федеральным законом, необходимо предоставить возможность достоверного установления личности участников. В России это возможно через проверку доступа к верифицированному аккаунту на Госуслугах.

Стек и схема интеграции

Для интеграции мы используем:

  • Typescript, ReactJS, NestJS

  • КриптоПро CSP 4

  • Docker, Kubernetes

Схема интеграции

Схема интеграции

Формирование подписи

Прежде чем разбирать все по порядку, кое о чем стоит подумать заранее. В отличие от других интеграций, запросы к ЕСИА должны сопровождаться подписью ГОСТ Р 34.10/11-2012, а не просто API key. Создать такую подпись можно с помощью утилиты КриптоПро CSP. Для нас основная задача здесь — правильно обернуть эту утилиту в Docker, чтобы с ней можно было работать как с отдельным сервисом в рамках нашей инфраструктуры. Получившийся сервис мы выложили в открытый доступ на гитхабе. Инструкция по запуску есть в README.md.

В процесс сборки Docker образа сервиса с утилитой КриптоПро мы встроили:

  • Установку утилиты КриптоПро СSP 4 из .deb пакета

  • Установку лицензии КриптоПро

  • Загрузку корневого сертификата тестовой или основной среды ЕСИА

  • Загрузку пользовательского сертификата с PIN кодом

  • REST-сервер с методом, позволяющим создавать подписи

Таким образом вся криптография собрана в отдельном самостоятельном компоненте, который можно использовать, когда необходимо что-нибудь подписать. Вот как это выглядит на бэкенде:

private async signParams(params: Record<string, string>) {
 const time = moment().format('YYYY.MM.DD HH:mm:ss ZZ')
 const state = uuid()
 const clientId = this.clientId
 const scope = this.scope

 const { data: { result: clientSecret } } = await axios.post<{ result: string }>(
   `${this.cryptoProServiceAddress}/cryptopro/sign`,
   { text: [scope, time, clientId, state].join('') },
 )

 return {
   ...params,
   timestamp: time,
   client_id: clientId,
   scope,
   state,
   client_secret: clientSecret.replace(/\n/g, ''),
 }
}

С созданием подписей разобрались, теперь последовательно разберем, как реализовать схему выше.

Создание ссылки для редиректа на страницу ЕСИА

Все начинается с того, что пользователь решает пройти авторизацию через ЕСИА. Создаем на бэкенде ссылку для перехода с использованием нашего инструмента формирования подписей.

async getAuthLink(redirectLink: string) {
 const params = await this.signParams({
   redirect_uri: redirectLink,
   response_type: 'code',
   access_type: 'offline',
 })
 const authQuery = new URLSearchParams(params)
 const authURL = `${this.esiaHost}/aas/oauth2/ac`
 return `${authURL}?${authQuery}`
}

В redirectLink необходимо указать адрес страницы, на которую ЕСИА перенаправит пользователя после успешной аутентификации. Созданную ссылку возвращаем на фронтенд и перенаправляем на нее пользователя.

Получение авторизационного токена ЕСИА

Запрос токена идентификации

После успешной аутентификации на странице ЕСИА пользователь возвращается на фронтенд приложения по указанному нами адресу. ЕСИА передаёт авторизационный токен в виде get-параметра code. Этот токен необходимо передать на бэкенд и запросить с его помощью идентификационный токен пользователя.

async getTokens(code: string) {
 try {
   const params = await this.signParams({
     grant_type: 'authorization_code',
     token_type: 'Bearer',
     redirect_uri: 'no',
     code,
   })
   const authURL = `${this.host}/aas/oauth2/te`
   const authQuery = new URLSearchParams(params)
   const { data: tokens } = await axios.post(`${authURL}?${authQuery}`)
   return {
     idToken: tokens.id_token,
     accessToken: tokens.access_token,
     refreshToken: tokens.refresh_token,
   }
 } catch (e) {
   const status = e.response ? e.response.status : 500
   const message = e.response ? e.response.data.error_description : e.message
   throw new HttpException('Failed to get auth tokens: ' + message, status)
 }
}

Получение данных о пользователе

Идентификационный токен пользователя необходимо проверить с помощью публичного RSA ключа от ЕСИА и получить из него id пользователя. С помощью этого id и accessToken, который мы получили в предыдущем шаге, мы уже наконец можем запросить персональные данные пользователя.

getUserIdFromToken(idToken: string) {
 const decodedIdToken = verify(idToken, this.esiaPublicKey, {
   algorithms: ['RS256'],
   audience: 'WE_VOTE',
 }) as EsiaParsedToken
 return decodedIdToken['urn:esia:sbj']['urn:esia:sbj:oid']
}

async getUserInfo(tokens: EsiaTokens) {

 const { idToken, accessToken } = tokens
 const oId = this.getUserIdFromToken(idToken)

 const [{ data: mainInfo }, { data: contactsInfo }] = await Promise.all([
   axios.get(`${this.esiaHost}/rs/prns/${oId}`, {
     headers: {
       Authorization: `Bearer ${accessToken}`,
     },
   }),
   axios.get(`${this.esiaHost}/rs/prns/${oId}/ctts?embed=(elements)`, {
     headers: {
       Authorization: `Bearer ${accessToken}`,
     },
   }),
 ])

 const email = contactsInfo.elements.find(({ type }: { type: string }) => type === 'EML')

 return {
   id: oId,
   firstName: mainInfo.firstName,
   lastName: mainInfo.lastName,
   surName: mainInfo.middleName,
   trusted: mainInfo.trusted,
   email: email ? {
     value: email.value.toLowerCase(),
     verified: email.vrfStu === 'VERIFIED',
   } : null,
 }
}

На этом шаге мы уже имеем все необходимые данные о пользователе. Остается только занести их в свою систему и закончить авторизацию.

Полный код интеграционного модуля на бэкенде

import { HttpException } from '@nestjs/common'
import * as moment from 'moment'
import { v4 as uuid } from 'uuid'
import { URLSearchParams } from 'url'
import axios from 'axios'
import { verify } from 'jsonwebtoken'

type EsiaTokens = {
 idToken: string,
 accessToken: string,
}

type EsiaParsedToken = {
 'urn:esia:sbj': {
   'urn:esia:sbj:oid': string,
 },
}

export class EsiaApiService {
 private readonly clientId = 'WE_VOTE'
 private readonly scope = ['openid', 'email', 'fullname'].join(' ')

 constructor(
   private readonly esiaHost: string, // 'https://esia-portal1.test.gosuslugi.ru' или 'https://esia.gosuslugi.ru'
   private readonly esiaPublicKey: string, // можно взять из http://esia.gosuslugi.ru/public/esia.zip
   private readonly cryptoProServiceAddress: string, // адрес сервиса по созданию подписей e.g 'http://127.0.0.1:3037'
 ) {
 }

 async getAuthLink(redirectLink: string) {
   const params = await this.signParams({
     redirect_uri: redirectLink,
     response_type: 'code',
     access_type: 'offline',
   })
   const authQuery = new URLSearchParams(params)
   const authURL = `${this.esiaHost}/aas/oauth2/ac`
   return `${authURL}?${authQuery}`
 }

 private async signParams(params: Record<string, string>) {
   const time = moment().format('YYYY.MM.DD HH:mm:ss ZZ')
   const state = uuid()
   const clientId = this.clientId
   const scope = this.scope

   const { data: { result: clientSecret } } = await axios.post<{ result: string }>(
     `${this.cryptoProServiceAddress}/cryptopro/sign`,
     { text: [scope, time, clientId, state].join('') },
   )

   return {
     ...params,
     timestamp: time,
     client_id: clientId,
     scope,
     state,
     client_secret: clientSecret.replace(/\n/g, ''),
   }
 }

 async getTokens(code: string) {
   try {
     const params = await this.signParams({
       grant_type: 'authorization_code',
       token_type: 'Bearer',
       redirect_uri: 'no',
       code,
     })
     const authURL = `${this.esiaHost}/aas/oauth2/te`
     const authQuery = new URLSearchParams(params)
     const { data: tokens } = await axios.post(`${authURL}?${authQuery}`)
     return {
       idToken: tokens.id_token,
       accessToken: tokens.access_token,
       refreshToken: tokens.refresh_token,
     }
   } catch (e) {
     const status = e.response ? e.response.status : 500
     const message = e.response ? e.response.data.error_description : e.message
     throw new HttpException('Failed to get auth tokens: ' + message, status)
   }
 }

 getUserIdFromToken(idToken: string) {
   const decodedIdToken = verify(idToken, this.esiaPublicKey, {
     algorithms: ['RS256'],
     audience: this.clientId,
   }) as EsiaParsedToken
   return decodedIdToken['urn:esia:sbj']['urn:esia:sbj:oid']
 }

 async getUserInfo(tokens: EsiaTokens) {

   const { idToken, accessToken } = tokens
   const oId = this.getUserIdFromToken(idToken)

   const [{ data: mainInfo }, { data: contactsInfo }] = await Promise.all([
     axios.get(`${this.esiaHost}/rs/prns/${oId}`, {
       headers: {
         Authorization: `Bearer ${accessToken}`,
       },
     }),
     axios.get(`${this.esiaHost}/rs/prns/${oId}/ctts?embed=(elements)`, {
       headers: {
         Authorization: `Bearer ${accessToken}`,
       },
     }),
   ])

   const email = contactsInfo.elements.find(({ type }: { type: string }) => type === 'EML')

   return {
     id: oId,
     firstName: mainInfo.firstName,
     lastName: mainInfo.lastName,
     surName: mainInfo.middleName,
     trusted: mainInfo.trusted,
     email: email ? {
       value: email.value.toLowerCase(),
       verified: email.vrfStu === 'VERIFIED',
     } : null,
   }
 }

}

Надеюсь, статья оказалась для вас полезной. Желаю, чтобы у вас все получилось без особых проблем! 

Полезные материалы по теме

  • Наш сервис по созданию подписей с использованием КриптоПро 

  • MVP-проект с Криптопро в докере

  • Методические указания по интеграции от ЕСИА

  • Инструкция по работе с тестовой средой ЕСИА

  • КриптоПро CSP

  • Интеграция на Java

  • Второй вариант интеграции на Java

  • Описание процесса OAuth2-интеграции

Данный документ описывает порядок регистрации портала записи пациента на прием к врачу, далее ИС (информационная система) в системе ЕСИА.

Применимо для регистрации других ИС с поправками на специфику.

Нормативные документы 

  • Руководство пользователя ЕСИА 
    https://digital.gov.ru/ru/documents/6182/ 
  • Руководство пользователя технологического портала ЕСИА 
    https://digital.gov.ru/ru/documents/6190/ 
  • Методические рекомендации по использованию ЕСИА 
    https://digital.gov.ru/ru/documents/6186/ 
  • Регламент информационного взаимодействия Участников с Оператором ЕСИА и оператором эксплуатации инфраструктуры электронного правительства 
    https://digital.gov.ru/ru/documents/4244/ 

Ресурсы:

Технологический портал (ПРОМЫШЛЕННАЯ СРЕДА): http://esia.gosuslugi.ru/console/tech 

Технологический портал (ТЕСТОВАЯ СРЕДА): https://esia-portal1.test.gosuslugi.ru/console/tech 

1) Зарегистрируйте вашу организацию в ЕСИА

Необходимо получить квалифицированную электронную подпись (КЭП) на руководителя организации и зарегистрировать юридическое лицо или орган государственной власти в профиле ЕСИА (п.3 Руководства пользователя ЕСИА). Вам потребуется КЭП юридического лица (в т.ч. это может быть подпись ЭП-СП). За получением средства КЭП нужно обратиться в один из аккредитованных Минкомсвязью России удостоверяющих центров вашего региона.

!

Если у вашей организации уже есть доступ к ЕСИА сразу перейти к п.2

2) Зарегистрируйте информационную систему в ЕСИА

Ответственном сотруднику необходимо предоставить доступ к технологическому порталу (п. 3.5.2.3 Руководства пользователя). В результате регистрации через технологический портал ваша информационная система заносится в реестр ИС, взаимодействующих с ЕСИА. Для ИС присваивается буквенно-цифровой код — мнемоника.

Сотрудник должен быть привязан к организации!

3) Сертификаты ИС

В ЕСИА создан механизм аутентификации пользователей, основанный на спецификациях OAuth 2.0 и расширении OpenID Connect 1.0.
Необходимо сгенерировать закрытый ключ и сертификат открытого ключа, зарегистрировать его в технологическом портале.
Подробно необходимые действия описаны в разделе 3.1. Методических рекомендаций.

ВАЖНО

С ноября 2019 года подключение ИС в ЕСИА осуществляется только с сертификатами, поддерживащими алгоритмы шифрования ГОСТ-2012. 

Портал записи на прием на данный момент работает только с ключами криптопровайдера  КриптоПРО. 

4) Подключитесь к тестовой среде ЕСИА

Необходимо отправить форму заявки на адрес sd@sc.minsvyaz.ru. Актуальная форма размещена в Регламенте взаимодействия — ПРИЛОЖЕНИЕ Е. ФОРМА ЗАЯВКИ НА СОГЛАСОВАНИЕ ПРАВА ИСПОЛЬЗОВАНИЯ ЕСИА И НА ПОДКЛЮЧЕНИЕ ИНФОРМАЦИОННОЙ СИСТЕМЫ К ЕСИА С ЦЕЛЬЮ ИСПОЛЬЗОВАНИЯ ПРОГРАММНЫХ ИНТЕРФЕЙСОВ ЕСИА ДЛЯ ИДЕНТИФИКАЦИИ И АУТЕНТИФИКАЦИИ ЗАЯВИТЕЛЕЙ

!

К заявке прилагаются файлы открытого (сертификата) и закрытого ключа в формате DER.

SCOPE

В заявке необходимо перечислить следующие SCOPE (типы запрашиваемых персональных данных гражданина)

Scope:
— openid
— fullname
— birthdate
— gender
— snils
— inn
— id_doc
— birthplace
— medical_doc
— drivers_licence_doc
— birth_cert_doc
— email
— mobile
— contacts
— usr_org
— kid_fullname
— kid_birthdate
— kid_gender
— kid_snils
— kid_inn
— kid_birth_cert_doc
— kid_medical_doc

Пример заполнения заявки: 

После получения доступа в тестовую среду необходимо произвести настройку сервиса подписи на портале. 

Для этого понадобится: 

  • сертификат в формате DER
  • пароль от сертификата
  • контейнер закрытых ключей
  • лицензионный ключ КриптоПРО

Данные ключи необходимо передать ответственному сотруднику СТП. Или настроить сервис подписи самостоятельно.

После настройки и проверки тестовой среды можно переходить к регистрации в промышленной среде.

5) Подключитесь к промышленной среде ЕСИА

Необходимо отправить форму заявки на адрес sd@sc.minsvyaz.ru. Форма заявки как при подключении к тестовой среде.

Проверить наличие ИС на технологическом портале ПРОМЫШЛЕННОЙ СРЕДЫ, а так же наличие и актуальность прикрепленных там сертификатов.

После получения доступа в промышленную среду, необходимо настроить сервис подписи портала для подписи запросов в ЕСИА. 

Для этого понадобится: 

  • сертификат в формате DER
  • пароль от сертификата
  • контейнер закрытых ключей
  • лицензионный ключ КриптоПРО

Данные ключи необходимо передать ответственному сотруднику СТП. Или настроить сервис подписи самостоятельно.

Проверить работоспособность портала — авторизоваться на портале записи на прием под учетной записью реального гражданина.

6) Доменные имена

Согласно ФЗ №8 «ОБ ОБЕСПЕЧЕНИИ ДОСТУПА К ИНФОРМАЦИИ О ДЕЯТЕЛЬНОСТИ ГОСУДАРСТВЕННЫХ ОРГАНОВ И ОРГАНОВ МЕСТНОГО САМОУПРАВЛЕНИЯ» информационные ресурсы (сайты) принадлежащие государственным или муниципальным организациям должны располагаться на доменах принадлежащих этим организациям. 

В связи с этим МИАЦ региона должен зарегистрировать доменное имя любого уровня для портала записи пациентов, а так же обеспечить доступ к сайту по защищенному протоколу HTTPS, для чего потребуется https сертификат.  

Cертификаты SSL (HTTPS)

Текущие доменные имена вида код_региона.2dr.ru остаются в рабочем состоянии как резервные. 

Единая система идентификации и авторизации (ЕСИА) – это единственный способ верифицировать личность пользователя. Если продукт работает с деньгами, решает юридические задачи или работает с медицинскими данными, без интеграции с ЕСИА не обойтись. Рассказываем, что нужно знать, чтобы работать с этой инфраструктурой.

ЕСИА появилась в 2010 году и изначально использовалась для авторизации на Портале госуслуг. За прошедшее время возможности системы постоянно развивались, и сегодня коммерческие организации используют её, чтобы связывать учётные записи пользователя с их оффлайн-личностью.

То есть если компании нужно удостовериться, что по ту сторону экрана действительно тот человек, которым представился пользователь, ЕСИА предоставляет такую возможность. И самое главное – эта идентификация имеет юридическую значимость.

Какие возможности открывает такая идентификация

1. Клиент может подписывать юридически значимые электронные документы, получать защищённый доступ к конфиденциальной информации, медицинским данным и т.д.

2. Появляется возможность автоматически заполнять в анкетах и заявках персональные данные клиента: ФИО, данные паспорта, ИНН, информация о детях и др. При этом компания может быть уверена, что эти данные абсолютно верны и правдивы.

3. Страховые компании и банки могут продавать через приложение свои продукты. И никаких расходов, которые связаны с традиционными, оффлайновыми каналами продаж – не нужно собирать документы, приглашать человека в офис, достаточно разработать скрипт для колл-центра.

4. Для пользователя верификация с ЕСИА повышает доверие к сервису и делает саму процедуру удобнее – не нужно помнить дополнительные пароли, просто нажимаешь знакомую кнопку и всё.

В наших проектах интеграция ЕСИА активно используется в продуктах страховых компаний. Это позволяет клиентам покупать полисы ОСАГО, отправлять извещения о ДТП при оформлении заявок на урегулирование убытков. Это критически важная функция для сценариев заявления о страховых случаях по ОСАГО, когда пользователь не является клиентом данной страховой компании.

Хотя сейчас к ЕСИА могут подключиться не все организации, можно ожидать, что такая авторизация скоро станет де-факто стандартом для пользовательских сервисов. Просто потому, что это надёжно и удобно для клиентов – вместо отдельной учётной записи для каждого ресурса можно использовать единый аккаунт «Госуслуг» и бесшовно пользоваться любыми нужными услугами. Поэтому задумываться об интеграции стоит всем компаниям.

Как информационная система работает с ЕСИА

ЕСИА является прослойкой между стандартным содержанием приложения и его защищёнными данными. Если пользователю не требуются услуги, которые требуют верификации личности, он может не проходить дополнительную авторизацию. Когда же он захочет попасть в этот раздел, приложение переадресует его на Портал госуслуг, а после успешной авторизации – вернёт обратно.

Технически процесс выглядит так:

1. Пользователь обращается к защищённому ресурсу информационной системы (например, при онлайн-покупке полиса ОСАГО).

2. Информационная система направляет в ЕСИА запрос на аутентификацию.

3. ЕСИА проверяет, есть ли у пользователя открытая сессия, т.е. авторизовался ли он уже ранее. Если такой сессии нет, ЕСИА направляет пользователя на веб-страницу, чтобы он ввёл свой логин и пароль.

4. После успешной аутентификации ЕСИА передаёт в информационную систему пакет с идентификационными данными пользователя, информацию об уровне его учётной записи и контексте аутентификации.

5. На основании этой информации система открывает пользователю доступ.

Как организации подключиться к ЕСИА

Процедура подключения занимает около месяца. Это время включает регистрацию необходимых аккаунтов, получение данных от Минцифры, работы по интеграции ИС.

1. Зарегистрируйте руководителя организации на Портале госуслуг. Регистрировать компании в ЕСИА могут только те их представители, которые вправе действовать без доверенности. Им понадобится подтверждённая учётная запись физического лица – т.е. нужно будет не только указать свои данные, но и обратиться в банк или МФЦ для верификации. В последнее время многие банки позволяют сделать это онлайн, через их приложения.

2. Зарегистрируйте вашу организацию.

a. Получите квалифицированную электронную подпись (КЭП) на руководителя организации.

b. Зарегистрируйте юридическое лицо в профиле ЕСИА.

c. Оформите КЭП для юридического лица.

Оформлением КЭП занимаются аккредитованные удостоверяющие центры. Подробная инструкция по этому процессу здесь.

3. Зарегистрируйте информационную систему в ЕСИА.

Регистрация системы происходит через технологический портал. Доступ к нему может получить один из сотрудников компании – действовать через аккаунт представителя уже не обязательно. Этот процесс подробно расписан в Руководстве пользователя технологического портала ЕСИА. В результате регистрации информационная система заносится в реестр ИС и получает мнемонический буквенно-цифровой код.

4. Доработайте систему для обмена данными с ЕСИА.

Аутентификация пользователей в ЕСИА происходит по OAuth 2.0 и OpenID Connect 1.0. Компании необходимо сгенерировать закрытый ключ и сертификат открытого ключа, зарегистрировать его на технологическом портале. Стоит отметить, что ЕСИА поддерживает только российские алгоритмы шифрования ГОСТ Р 34.10-2012 и ГОСТ Р 34.11-2012.

Стоит отдельно отметить, что если в компании уже используются средства верификации пользователей посредством Single Sign-On, то особых технических трудностей при подключении к ЕСИА не будет.

5. Подключитесь к тестовой среде ЕСИА

На этом этапе нужно отправить на адрес [email protected] заявку по форме, которая приводится в Регламенте взаимодействия заявителей с операторами ЕСИА. Когда администраторы откроют доступ, компании нужно подключить свою систему к ЕСИА, чтобы она могла принимать и отправлять запросы. Для этого используются специальные коннекторы, и Минцифры не даст разрешение на полноценный запуск, пока коннекторы не заработают стабильно в тестовом режиме.

6. Подключитесь к промышленной среде ЕСИА

Когда всё готово, вы отправляете ещё одну заявку на [email protected]. Остаётся проверить работоспособности интеграции – и готово.

Полезные ссылки

Время на прочтение
15 мин

Количество просмотров 11K

Предисловие

Передо мной стояла задача по интеграции нашего сервиса с госуслугами. Казалось ничего сложного не предстоит, но учитывая что наш сервис базируется на технологии ASP.NET всё было не так оптимистично. В начале были поиски.. много поисков, которые привели к множеству разрозненной и чаще всего неактуальной информации. Так же были найдены уже готовые решения, но как заявляли некоторые товарищи на форумах за такое могут и по головке погладить. Поэтому было решено писать самому.

Эта статья скорее больше актуализация и дополнение информации из этой статьи.

Введение

На сайте Минцифр есть методичка максимально раздутая и очень запутанная, но пользоваться ею нам всё равно придётся. Мы будем работать с ЕСИА версии 3.11 (актуальная на момент написания статьи). Кратко наши действия заключаются вот в чем:

  1. Регистрация ИС в регистре информационных систем ЕСИА

  2. Регистрация ИС в тестовой среде

  3. Выполнение доработки системы для взаимодействия с ЕСИА

Звучит довольно просто, но каждый шаг целая отдельная история приключений. Регистрация ИС в ЕСИА приключение для бюрократа. Поэтому в этой статье мы немного посмотрим на второй шаг, и детально распишем реализацию.

Содержание

  • Настройка ИС

  • Сертификаты ИС

  • Получаем client_certificate_hash

  • Формирование client_secret

  • Собираем ссылку для авторизации в Госуслугах

  • Получение токена доступа

  • Проверка токена

  • Получение данных пользователя из ЕСИА

Всё необходимое

Минцифры требуют использование сертифицированного ПО для криптографии. Поэтому мы будем использовать КриптоПРО CSP + КриптоПРО .Net + КриптоПРО .NetSDK. Всё это можно скачать с офф. сайта КриптоПРО. На время разработки лучше использовать триал версию.

Наш инвентарь для путешествия:

  • КриптоПРО CSP

  • КриптоПРО .Net

  • КриптоПРО .NetSDK

  • Контейнер закрытого ключа с сертификатом нашей организации

  • Много терпения

Немного о КриптоПРО CSP + .Net Core 5+

Вот тут и начинаются первые проблемы. На момент написания статьи у КриптоПРО .Net нет поддержки .Net Core 5 и выше. Есть сборка под .Net Core 3.1 но и она выглядит сомнительно. Поэтому было решено поднять сервис для .Net Framework 4.8 который будет использовать средства КриптоПРО CSP для подписания с использованием ЭЦП, а так же проверки ответов от ЕСИА.

Немного о контейнере закрытого ключа и сертификата

Когда мы начинали делать эту задачу у нас была КЭП на токене, но как оказалось на нём был неэкспортируемый контейнер. Скажу сразу, что экспортировать контейнер с такого токена запрещено ФНС. Поэтому необходимо заранее получить токен на имя сотрудника с экспортируемым контейнером. Так как его необходимо будет скопировать на сервер.

Приступаем

Начнём с того, что вы уже отправили заявку регистрации ИС в ЕСИА и её приняли. А так же отправили заявка на тестовую среду. Приступим к этапу настройки ИС в тестовом кабинете электронного правительства. Вот ссылка на тестовую страницу. Логинимся под тестовой учетной записью тестового пользователя 006(все данные лежат в приложении к работе с тестовой средой), так как он имеет доступ к управлением ИС.

Кабинет тестовой среды - Технологический порталйт

Кабинет тестовой среды — Технологический порталйт

Здесь ищем нашу систему по Мнемонике или полному названию, если таковой нет то создаём. Напротив нашей системы есть две кнопки:
Первая кнопка — изменить нашу ИС (информация о ИС, редиректы и тд)
Вторая кнопка — наши сертификаты с помощью которых мы подписываем сообщения в ЕСИА

Настройка ИС

Есть важный момент в настройки ИС. Это URL системы. Тут мы указываем ссылки куда ЕСИА может делать переадресацию при запросе от нашей ИС. На эти точки будет приходить авторизационный код (Если он указан в запросе).

Сертификаты ИС

Здесь мы можем загрузить наш сертификаты или же удалить их. Есть один важный момент, каждая ИС может иметь только один уникальный сертификат. А связи с тем, что на тестовой среде все системы регистрируются под одним пользователем и сертификаты тестовые одни на всех часта такая ситуация, что кто-то удаляет у вас сертификат и загружает к себе. А ваши запросы теперь падают с ошибкой) Но если у вас уже готов ЭЦП на сотудника, то лучше используйте её.

Реализуем

Мы закончили с настройки нашей ИС и можем приступить к реализации. Надеюсь вы уже установили КриптоПРО и всё необходимое для него. Если нет, я подожду…

Устанавливаем сертификаты

Такс~ Всё готово. Качаем сертификаты по ссылке из методички. Специально не буду вставлять, так как может измениться.

Здесь нам интересен сертификат ТЕСИА ГОСТ 2012.cer — это сертификат с помощью которого ЕСИА подписывает сообщения отправляя в нашу ИС. (Соответственно для продуктовой среды свой сертификат). Устанавливаем сертификат как доверенный. Здесь ничего сложного думаю разберётесь.

Теперь устанавливаем тестовый контейнер и сертификат. Для примера будем использовать предоставленные ЕСИА контейнеры, но вы можете использовать свои. Всё это лежит внутри архива.

Сам архив со всеми тестовыми контейнерами

Сам архив со всеми тестовыми контейнерами
Мы возьмём именно 006 так как на него зарегистрирована наша ИС
Мы возьмём именно 006 так как на него зарегистрирована наша ИС

В архиве лежит папка d1f73ca5.000 — это контейнер нам необходимо его переместить по пути C:\Users\User\AppData\Local\Crypto Pro

Теперь открываем КриптоПРО CSP. Выбираем установить личный сертификат и указываем Тестовое ведомство Фамилия006 ИО.cer и нажимаем найти автоматически. Выполняем оставшиеся шаги сами.

Механизм подписания

Пожалуй начинается самая важная и самая запутанная часть всего пути. Здесь мы реализуем сервис для работы с подписью. И так делаю выжимку из методических материалов, чтобы Вам не пришлось читать много текста.

Для получения авторизационный ссылки — ссылка на которую мы будем переадресовывать пользователя для авторизации в ЕСИА. Нам необходимо собрать ссылку из параметров.

  1. client_id — наша Мнемоника

  2. client_secret — Отсоединённая подпись от параметров запроса в кодировке UTF-8

  3. redirect_uri — ссылка на которую ЕСИА будет переадресовывать пользователя вместе с авторизационным кодом

  4. scope — перечень запрашиваемой информации. Например fullname birthdate gender

  5. response_type — тип ответа от ЕСИА, в нашем случае это просто строчка code

  6. state — Идентификатор текущего запроса. Генерируется таким образом Guid.NewGuid().ToString("D");

  7. timestamp — время запроса авторизационного кода в формате yyyy.MM.dd HH:mm:ss Z. Генерируется таким образом DateTime.UtcNow.ToString("yyyy.MM.dd HH:mm:ss +0000");

  8. client_certificate_hash — это fingerprint сертификата в HEX-формате.

Обозначили наш зоопарк. Самый важный зверь здесь client_secret

Получаем client_certificate_hash

В методическом указании от Минцифр есть ссылка на специальную утилиту с помощью которой мы можем получить этот хэш. Разархивировали архив и видим перед нами sh. Windows пользователи не пугаемся, на самом деле тут же лежит .exe файл. Чтобы вычислить хэш нашего сертификат просто необходимо из cmd запустить вот такой скрипт:

cpverify.exe test.cer -mk -alg GR3411_2012_256 -inverted_halfbytes 0

Формирование client_secret

Такс перед тем как просто получит client_secret нам необходимо сделать:

  • ASP.Net Framework 4.8 WebAPI — тот самый сервис который будет работать с КриптоПРО CSP

Пропустим множество шагов создания этого сервиса и перейдём сразу к его настройки для работы с КриптоПРО CSP.

Настройка сервиса для работы с КриптоПРО CSP

Добавляем ссылки на DLL КриптоПРО.
Переходим по пути C:\Program Files (x86)\Crypto Pro.NET SDK\Assemblies\4.0
Выбираем всё что нам нужно. (подробная информация)

Теперь мы имеем доступ к API КриптоПРО CSP из кода .Net Framework

Теперь создаём контроллер:

Код контроллера

Итак нам необходимо получать строку для подписания. Создадим метод

const string CertSerialNumber = "01f290e7008caed0904b967783fd0e4ad6";
const string EsiaCertSerialNumber = "0125657e00a1ae59804d92116214e53466";

[HttpGet]
public string Get(string msg)
{
    msg = Base64UrlEncoder.Decode(msg);

    var data = Encoding.UTF8.GetBytes(msg);

    var client_secret = Sign(data);

    return client_secret;
}

Мы заранее укажем константами серийные номера сертификатов.
В методе Get получаем строку в Base64Url формате, чтобы спокойно передавать наши длинные сообщения.
Декодируем строку из Base64Url в текст. После чего переводим текст в байты используя UTF-8. А теперь подписываем.

string Sign(byte[] data)
{
    var gost3411 = new Gost3411_2012_256CryptoServiceProvider();
    var hashValue = gost3411.ComputeHash(data);
    gost3411.Clear();
    var signerCert = GetSignerCert();
    var SignedHashValue = GostSignHash(hashValue,
        signerCert.PrivateKey as Gost3410_2012_256CryptoServiceProvider, "Gost3411_2012_256");
    var client_secret = Base64UrlEncoder.Encode(SignedHashValue);

    return client_secret;
}

И так что мы тут делаем. С помощью ГОСТ 34.11-2012 мы вычисляем хэш нашего сообщения. И используя полученный сертификат подписываем сообщение.

X509Certificate2 GetSignerCert()
{
    var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
    var certificates = store.Certificates.Find(X509FindType.FindBySerialNumber, CertSerialNumber, false);

    if (certificates.Count != 1)
    {
        return null;
    }

    var certificate = certificates[0];

    if (certificate.PrivateKey == null)
    {
        return null;
    }

    return certificate;
}

Здесь мы открываем наш склад с контейнерами и ищем именно тот где лежит наш сертификат. После чего извлекаем из него сертификат.

byte[] GostSignHash(byte[] HashToSign, Gost3410_2012_256CryptoServiceProvider key, string HashAlg)
{
    try
    {
        //Создаем форматтер подписи с закрытым ключом из переданного 
        //функции криптопровайдера.
        var Formatter = new Gost2012_256SignatureFormatter(
            (Gost3410_2012_256CryptoServiceProvider) key);

        //Устанавливаем хэш-алгоритм.
        Formatter.SetHashAlgorithm(HashAlg);

        //Создаем подпись для HashValue и возвращаем ее.
        return Formatter.CreateSignature(HashToSign);
    }
    catch (CryptographicException e)
    {
        Console.WriteLine(e.Message);
        return null;
    }
}

С помощью этого кода как раз и создаётся наша подпись на хэш строки. Здесь используется ГОСТ 34.10-2012.

Итак контроллер готов. Теперь переходим в наш основной проект на .Net Core

Создаём строку подписания. Просто выполняем конкатенацию параметры без разделителей. Здесь я использую IOptions чтобы брать параметры из appsettings.json.

var msg = $"{esiaSettings.Value.ClientId}{esiaSettings.Value.Scope}{timestamp}{state}{redirectUri}";

Мы получил строку для подписания. Теперь нам необходимо эту строку закодировать в Base64Url и отправляем её на подписание в написанный нами заранее сервис

private string GetClientSecret(string msg){
  var client = new HttpClient();

  var msgBase64 = Base64UrlEncoder.Encode(msg);
  
  var response = await client.GetAsync($"{cryptoProSettings.Value.BaseUrl}/Get?msg={msgBase64}");
  
  var clientSecret = await response.Content.ReadAsStringAsync();
  
  clientSecret = JsonConvert.DeserializeObject<string>(clientSecret);
  
  return clientSecret;
}

Собираем ссылку для авторизации в Госуслугах

Наконец-то мы получили этот долгожданный секрет. Но вы могли бы подумать это всё, дальше всё просто и ясно. Не тут то было! Дело в том, что ЕСИА требует Base64 Url Safe кодироку. И она немного отличается от Base64Url кодировки доступной из коробки .Net
Итак дело за малым, собираем нашего гомункула из секрета и параметров.

Класс помощник для сборки ссылки

Возможно излишне, но мне понравился метод сбора вот таким способом.

public class RequestBuilder
{
    List<RequesItemClass> items = new List<RequesItemClass>();
    public void AddParam(string name, string value)
    {
        items.Add(new RequesItemClass { name = name, value = value });
    }
    public override string ToString()
    {
        return string.Join("&", items.Select(a => a.name + "=" + a.value));
    }
}

public class RequesItemClass
{
    public string name;
    public string value;
}

Код сборки ссылки

async Task<string> UrlBuild(string redirectUri)
{
    using var client = new HttpClient();

    var timestamp = DateTime.UtcNow.ToString("yyyy.MM.dd HH:mm:ss +0000");
    var state = Guid.NewGuid().ToString("D");

    var msg = $"{esiaSettings.Value.ClientId}{esiaSettings.Value.Scope}{timestamp}{state}{redirectUri}";

    var clientSecret = await GetClientSecret(msg);

    var builder = new RequestBuilder();
    builder.AddParam("client_secret", clientSecret);
    builder.AddParam("client_id", esiaSettings.Value.ClientId);
    builder.AddParam("scope", esiaSettings.Value.Scope);
    builder.AddParam("timestamp", timestamp);
    builder.AddParam("state", state);
    builder.AddParam("redirect_uri", redirectUri);
    builder.AddParam("client_certificate_hash", esiaSettings.Value.ClientCertificateHash);
    builder.AddParam("response_type", "code");
    builder.AddParam("access_type", "online");

    //Вот тут самый важный момент на который было потрачено множество времени. Просто заменяем символы на безопасные
    var url = esiaSettings.Value.EsiaAuthUrl + "?" + builder.ToString().Replace("+", "%2B")
        .Replace(":", "%3A")
        .Replace(" ", "+");

    return url;
}

Получаем ссылку на подобии вот такой:
Здесь https://esia-portal1.test.gosuslugi.ru/aas/oauth2/v2/ac ссылка на конечную точку получения авторизационно кода, указана в методическом материале.

https://esia-portal1.test.gosuslugi.ru/aas/oauth2/v2/ac?client_secret=v_c33_-LpkyKJbopTEYqBMbGZrBy9r9u1pzbRmMLNlJPcBnPTJj6Xx5DuxXba3EZZoXdMsb0YIwPDCoF0dfYjQ&client_id=MEMONIKA&scope=fullname+birthdate+gender&timestamp=2022.12.23+16%3A37%3A45+%2B0000&state=3a19c4d7-594b-496f-aa6e-970c75a925a4&redirect_uri=https%3A//api.site/users/esia&client_certificate_hash=EED1079A4FF154E117EAA196DCB551930807825DE1DE15EAF7607F354BA47423&response_type=code&access_type=online

Теперь перенаправляем пользователя по этой ссылке и ожидаем пока он авторизуется. После авторизации ЕСИА переадресует его на нашу ссылку и отправит туда в виде аргументов авторизационный код и state.

Получение токена доступа

Теперь время получить токен взамен на авторизационный код.

Метод для получение токена

public async Task<EsiaAuthToken> GetToken(string authorizationCode, string redirectUrl)
{
    var timestamp = DateTime.UtcNow.ToString("yyyy.MM.dd HH:mm:ss +0000");
    var state = Guid.NewGuid().ToString("D");

    var msg =
        $"{esiaSettings.Value.ClientId}{esiaSettings.Value.Scope}{timestamp}{state}{redirectUrl}{authorizationCode}";

    var clientSecret = await GetClientSecret(msg);

    var requestParams = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("client_id", esiaSettings.Value.ClientId),
        new KeyValuePair<string, string>("code", authorizationCode), //Здесь мы передаём полученный код
        new KeyValuePair<string, string>("grant_type", "authorization_code"),  //Просто указываем тип
        new KeyValuePair<string, string>("state", state),
        new KeyValuePair<string, string>("scope", esiaSettings.Value.Scope),
        new KeyValuePair<string, string>("timestamp", timestamp),
        new KeyValuePair<string, string>("token_type", "Bearer"),  //Какой токен мы хотим получить
        new KeyValuePair<string, string>("client_secret", clientSecret),
        new KeyValuePair<string, string>("redirect_uri", redirectUrl),
        new KeyValuePair<string, string>("client_certificate_hash", esiaSettings.Value.ClientCertificateHash)
    };

    using var client = new HttpClient();
    using var response = await client.PostAsync(esiaSettings.Value.EsiaTokenUrl,
        new FormUrlEncodedContent(requestParams));
    response.EnsureSuccessStatusCode();
    var tokenResponse = await response.Content.ReadAsStringAsync();

    var token = JsonConvert.DeserializeObject<EsiaAuthToken>(tokenResponse);

    if (!await ValidatingAccessToken(token))
    {
        throw new Exception("Ошибка проверки маркера индентификации");
    }

    return token;
}

Тут всё простенько, снова генерируем client_secret указываем остальные параметры и отправляем запрос в ЕСИА на получение токена. Тестовый Uri https://esia-portal1.test.gosuslugi.ru/aas/oauth2/v3/te

Класс токена

public class EsiaAuthToken
{
    /// <summary>
    /// Токен доступа
    /// </summary>
    [JsonProperty("access_token")]
    public string AccessToken { get; set; }

    /// <summary>
    /// Идентификатор запроса
    /// </summary>
    public string State { get; set; }

    string[] parts => AccessToken.Split('.');

    /// <summary>
    /// Хранилище данных в токене
    /// </summary>
    public EsiaAuthTokenPayload Payload
    {
        get
        {
            if (string.IsNullOrEmpty(AccessToken))
            {
                return null;
            }

            if (parts.Length < 2)
            {
                throw new Exception($"При расшифровке токена доступа произошла ошибка. Токен: {AccessToken}");
            }

            var payload = Encoding.UTF8.GetString(Base64UrlEncoder.DecodeBytes(parts[1]));
            return JsonConvert.DeserializeObject<EsiaAuthTokenPayload>(payload);
        }
    }

    /// <summary>
    /// Сообщение для проверки подписи
    /// </summary>
    [Newtonsoft.Json.JsonIgnore]
    public string Message
    {
        get
        {
            if (string.IsNullOrEmpty(AccessToken))
            {
                return null;
            }

            if (parts.Length < 2)
            {
                throw new Exception($"При расшифровке токена доступа произошла ошибка. Токен: {AccessToken}");
            }

            return parts[0] + "." + parts[1];
        }
    }

    /// <summary>
    /// Сигнатура подписи
    /// </summary>
    [Newtonsoft.Json.JsonIgnore]
    public string Signature
    {
        get
        {
            if (string.IsNullOrEmpty(AccessToken))
            {
                return null;
            }

            if (parts.Length < 2)
            {
                throw new Exception($"При расшифровке токена доступа произошла ошибка. Токен: {AccessToken}");
            }

            return parts[2];
        }
    }

    public class EsiaAuthTokenPayload
    {
        [JsonConstructor]
        public EsiaAuthTokenPayload(string tokenId, string userId, string nbf, string exp, string iat, string iss,
            string client_id)
        {
            TokenId = tokenId;
            UserId = userId;
            BeginDate = EsiaHelper.DateFromUnixSeconds(double.Parse(nbf));
            ExpireDate = EsiaHelper.DateFromUnixSeconds(double.Parse(exp));
            CreateDate = EsiaHelper.DateFromUnixSeconds(double.Parse(iat));
            Iss = iss;
            ClientId = client_id;
        }

        /// <summary>
        /// Идентификатор токена
        /// </summary>
        [JsonProperty("urn:esia:sid")]
        public string TokenId { get; private set; }

        /// <summary>
        /// Идентификатор пользователя
        /// </summary>
        [JsonProperty("urn:esia:sbj_id")]
        public string UserId { get; private set; }

        /// <summary>
        /// Время начала действия токена
        /// </summary>
        [JsonPropertyName("nbf")]
        public DateTime BeginDate { get; private set; }

        /// <summary>
        /// Время окончания действия токена
        /// </summary>
        [JsonPropertyName("exp")]
        public DateTime ExpireDate { get; private set; }

        /// <summary>
        /// Время выпуска токена
        /// </summary>
        [JsonPropertyName("iat")]
        public DateTime CreateDate { get; private set; }

        /// <summary>
        /// Организация, выпустившая маркер
        /// </summary>
        [JsonPropertyName("iss")]
        public string Iss { get; private set; }

        /// <summary>
        /// Адресат маркера
        /// </summary>
        [JsonPropertyName("client_id")]
        public string ClientId { get; private set; }
    }
  }

  public static class EsiaHelper
  {
      public static DateTime DateFromUnixSeconds(double seconds)
      {
          var date = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

          return date.AddSeconds(seconds).ToLocalTime();
      }
  }

Проверка токена

Итак помимо того, что нам нужно получить токен, нам так же необходимо проверить его.

Сам токен состоит из 3 частей.
1 часть — заголовок JWT токена
2 часть — payload токена, там вся основная информация о токене
3 часть — RAW подпись в формате UTF-8

Код конечной точки для проверки подписи

[HttpPost]
public bool Verify(VerifyMessage message)
{
    try
    {
        return VerifyRawSignString(message.Message, message.Signature);
    }
    catch (Exception ex)
    {
        return false;
    }
}

public class VerifyMessage
{
    public string Signature { get; set; }
    public string Message { get; set; }
}

Код проверки подписи на нашем сервисе

/// <summary>
/// Проверка подписи JWT в формате HEADER.PAYLOAD.SIGNATURE.
/// </summary>
/// <param name="message">HEADER.PAYLOAD в формате Base64url</param>
/// <param name="signature">SIGNATURE в формате Base64url</param>
bool VerifyRawSignString(string message, string signature)
{
    var signerCert = GetEsiaSignerCert();

    var messageBytes = Encoding.UTF8.GetBytes(message);
    var signatureBytes = Base64UrlEncoder.DecodeBytes(signature);
    //Переварачиваем байты, так как используется RAW подпись
    Array.Reverse(signatureBytes, 0, signatureBytes.Length);

    using (var GostHash = new Gost3411_2012_256CryptoServiceProvider())
    {
        var csp = (Gost3410_2012_256CryptoServiceProvider) signerCert.PublicKey.Key;
        //Используем публичный ключ сертификата для проверки  
        return csp.VerifyData(messageBytes, GostHash, signatureBytes);
    }
}

Код получения сертификата ЕСИА

X509Certificate2 GetEsiaSignerCert()
{
    var store = new X509Store(StoreName.AddressBook, StoreLocation.CurrentUser);
    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
    var certificates = store.Certificates.Find(X509FindType.FindBySerialNumber, EsiaCertSerialNumber, false);

    var certificate = certificates[0];

    return certificate;
}

Здесь используем введённые ранее константы. И Получаем сертификат из доверенных сертификатов.

Отправка токена на проверку

public async Task<bool> ValidatingAccessToken(EsiaAuthToken token)
{
    if (token.Payload.ExpireDate <= DateTime.Now ||
        token.Payload.BeginDate >= DateTime.Now ||
        token.Payload.CreateDate >= DateTime.Now ||
        token.Payload.ExpireDate <= token.Payload.BeginDate ||
        token.Payload.CreateDate > token.Payload.BeginDate ||
        token.Payload.CreateDate > token.Payload.ExpireDate ||
        token.Payload.Iss != esiaSettings.Value.ISS ||
        token.Payload.ClientId != esiaSettings.Value.ClientId)
    {
        return false;
    }

    var client = new HttpClient();

    var requestParams = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>("signature", token.Signature),
        new KeyValuePair<string, string>("message", token.Message)
    };

    var response = await client.PostAsync($"{cryptoProSettings.Value.BaseUrl}/Verify",
        new FormUrlEncodedContent(requestParams));

    response.EnsureSuccessStatusCode();
    var resultResponse = await response.Content.ReadAsStringAsync();

    var result = JsonConvert.DeserializeObject<bool>(resultResponse);

    return result;
}

Этот код используем в нашем основном сервисе.
Проверяем поля токена на актуальность, чтобы его не могли подделать. А потом уже проверяем подпись токена, как указано в методических указаниях.

Получение данных пользователя из ЕСИА

Имея токен мы может отправить запрос на получение данных о пользователе указанных в scope токена. Пример кода, где мы получаем данные пользователя. Здесь esiaUserId содержится в самом токене, это уникальный идентификатор пользователя ЕСИА. Наш токен указываем в заголовке авторизации.

public async Task<EsiaUser> ExecuteAsync(string esiaUserId, string accessToken)
{
    using (var client = new HttpClient())
    {
        client.DefaultRequestHeaders.Clear();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        var response = await client.GetStringAsync($"{esiaSettings.Value.EsiaRestUrl}/prns/{esiaUserId}");
        var user = JsonConvert.DeserializeObject<EsiaUser>(response);
        user.Id = user.Id ?? esiaUserId;

        return user;
    }
}

Код класса EsiaUser

public class EsiaUser
{
    /// <summary>
    /// Идентификатор
    /// </summary>
    [JsonProperty("oid")]
    public string Id { get; set; }

    /// <summary>
    /// Фамилия
    /// </summary>
    [JsonProperty("firstName")]
    public string FirstName { get; set; }

    /// <summary>
    /// Имя
    /// </summary>
    [JsonProperty("lastName")]
    public string LastName { get; set; }

    /// <summary>
    /// Отчество
    /// </summary>
    [JsonProperty("middleName")]
    public string MiddleName { get; set; }

    /// <summary>
    /// Дата рождения
    /// </summary>
    [JsonProperty("birthdate")]
    public string Birthdate { get; set; }

    /// <summary>
    /// Пол
    /// </summary>
    [JsonProperty("gender")]
    public string Gender { get; set; }

    /// <summary>
    /// Подтвержден ли пользователь
    /// </summary>
    [JsonProperty("trusted")]
    public bool Trusted { get; set; }
}

Заключение

Наконец мы закончили интеграцию с ЕСИА. Это был длинный путь полный странных вещей. Неясных решений и множество потраченного времени. Надеюсь этой статьёй я помог Вам реализовать задачу интеграции гораздо быстрее и легче. Спасибо за потраченное время.

Понравилась статья? Поделить с друзьями:
  • Стиральная машина электролюкс steamsystem 7 kg wash and dry инструкция
  • Назовите событие непосредственно подтолкнувшее руководство большевистской партии к принятию решения
  • Руководство верховного совета рсфср
  • Пантера slk 625 rs инструкция по установке
  • Parodium гель инструкция по применению для десен