Esia-oauth2 Goto Github PK

Esia-oauth2 
 Goto Github
 PK pos gosuslugi

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

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

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

Сделать это оказалось не так просто. Нужно было выполнить ряд требований и процедур, решить технические трудности.

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

Надеемся, наш опыт поможет Java-разработчикам (и не только) сэкономить массу времени при разработке и ознакомлении с методическими рекомендациями Минкомсвязи.

Esia-oauth2 
 Goto Github
 PK

Зачем нам нужна интеграция с ЕСИА?

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

Esia-oauth2 
 Goto Github
 PK

Кроме того, интеграция с ЕСИА позволила Русфинанс Банку:

  • сократить время заполнения онлайн-анкет;
  • уменьшить количество отказов пользователей при попытке заполнить большое количество полей вручную;
  • обеспечить поток более «качественных», верифицированных клиентов.

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

Что делать и как?

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

Для начала важно было наметить план действий. Наш план включал следующие основные шаги:

  • подать заявки на использование программных интерфейсов ЕСИА в тестовой и промышленной среде;
  • самостоятельно разработать механизм взаимодействия с ЕСИА (в соответствии с действующим документом «Методические рекомендации по использованию ЕСИА»);
  • протестировать работу механизма в тестовой и промышленной среде ЕСИА.

Обычно мы разрабатываем наши проекты на Java. Поэтому для программной реализации выбрали:

  • IntelliJ IDEA;
  • КриптоПро JCP (или КриптоПро Java CSP);
  • Apache HttpClient;
  • Lombok;
  • FasterXML/Jackson.

Получение URL для переадресации

Первый шаг ― это получение авторизационного кода. В нашем случае это делает отдельный сервис с переадресацией на страницу авторизации портала Госуслуг (расскажем об этом немного подробнее).

Сначала мы инициализируем переменные ESIA_AUTH_URL (адрес ЕСИА) и API_URL (адрес, на который происходит редирект в случае успешной авторизации). После этого создаем объект EsiaRequestParams, который содержит в своих полях параметры запроса к ЕСИА, и сформируем ссылку esiaAuthUri.

Для наглядности покажем, как может выглядеть класс EsiaRequestParams:

Каждый запрос к ЕСИА имеет параметр client_secret, который представляет собой откреплённую электронную подпись в формате PKCS7 (Public Key Cryptography Standard). В нашем случае для подписи используется сертификат, который был получен удостоверяющим центром перед началом работ по интеграции с ЕСИА. Как работать с хранилищем ключей хорошо описано в этом цикле статей.

Для примера покажем, как выглядит хранилище ключей, предоставляемое компанией КриптоПро:

Esia-oauth2 
 Goto Github
 PK

Вызов приватного и публичного ключей в этом случае будет выглядеть так:

Читайте также:  Московские надбавки увеличатся с 1 апреля

KeyStore keyStore = KeyStore.getInstance(“HDImageStore”); // Создание экземпляра хранилища
keyStore.load(null, null);
PrivateKey privateKey = (PrivateKey) keyStore.getKey(esiaKeyStoreParams.getName(), esiaKeyStoreParams.getValue().toCharArray()); // Получение приватного ключа
X509Certificate certificate = (X509Certificate) keyStore.getCertificate(esiaKeyStoreParams.getName()); // Получение сертификата, он же – открытый ключ.

Где JCP.HD_STORE_NAME ― имя хранилища в КриптоПро, esiaKeyStoreParams.getName() ― имя контейнера и esiaKeyStoreParams.getValue().toCharArray() ― пароль контейнера.
В нашем случае не нужно загружать данные в хранилище методом load(), так как ключи уже будут там при указании имени этого хранилища.

Здесь важно помнить, что получения подписи в виде

нам недостаточно, так как ЕСИА требует откреплённую подпись формата PKCS7. Поэтому следует создать подпись формата PKCS7.

Пример нашего метода, возвращающего откреплённую подпись, выглядит следующим образом:

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

Укажем лишь некоторые детали:

  • rawClientSecret.getBytes() ― байтовый массив scope, timestamp, clientId и state;
  • localPrivateKey ― приватный ключ из контейнера;
  • localCertificate ― публичный ключ из контейнера;
  • true ― булево значение параметра подписи ― открепленная или нет.

Пример создания подписи можно найти в java-библиотеке КриптоПро, там стандарт PKCS7 называется CMS. А также в руководстве программиста, которое лежит вместе с исходниками скаченной версии КриптоПро.

Получение токена

Следующий шаг ― получение маркера доступа (он же токен) в обмен на авторизационный код, который был получен в качестве параметра при успешной авторизации пользователя на портале Госуслуг.

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

URI getTokenUri = new URIBuilder(ESIA_TOKEN_API_URL)
.addParameters(Arrays.asList(
new BasicNameValuePair(RequestEnum.CLIENT_ID.getParam(), requestDto.getClientId()),
new BasicNameValuePair(RequestEnum.CODE.getParam(), code),
new BasicNameValuePair(RequestEnum.GRANT_TYPE.getParam(), requestDto.getGrantType()),
new BasicNameValuePair(RequestEnum.CLIENT_SECRET.getParam(), requestDto.getClientSecret()),
new BasicNameValuePair(RequestEnum.STATE.getParam(), requestDto.getState()),
new BasicNameValuePair(RequestEnum.REDIRECT_URI.getParam(), requestDto.getRedirectUri()),
new BasicNameValuePair(RequestEnum.SCOPE.getParam(), requestDto.getScope()),
new BasicNameValuePair(RequestEnum.TIMESTAMP.getParam(), requestDto.getTimestamp()),
new BasicNameValuePair(RequestEnum.TOKEN_TYPE.getParam(), requestDto.getTokenType())
))
.build();
HttpUriRequest getTokenPostRequest = RequestBuilder.post()
.setUri(getTokenUri)
.setHeader(HttpHeaders.CONTENT_TYPE, “application/x-www-form-urlencoded”)
.build();

Получив ответ, распарсим его и получим токен:

Токен представляет собой строку, состоящую из трёх частей и разделённых точками: HEADER.PAYLOAD.SIGNATURE, где:

  • HEADER ― это заголовок, имеющий в себе свойства токена, в том числе алгоритм подписи;
  • PAYLOAD ― это информация о токене и субъекте, которую запрашиваем у Госуслуг;
  • Signature ― это подпись HEADER.PAYLOAD.

Валидация токена

В соответствии с методическими указаниями необходимо проверять срок действия маркера. Если срок действия истек, то нужно создать новую ссылку с дополнительными параметрами и сделать запрос с помощью http-клиента:

URI refreshTokenUri = new URIBuilder(ESIA_TOKEN_API_URL)
.addParameters(Arrays.asList(
new BasicNameValuePair(RequestEnum.CLIENT_ID.getParam(), requestDto.getClientId()),
new BasicNameValuePair(RequestEnum.REFRESH_TOKEN.getParam(), tokenResponseDto.getRefreshToken()),
new BasicNameValuePair(RequestEnum.CODE.getParam(), code),
new BasicNameValuePair(RequestEnum.GRANT_TYPE.getParam(), EsiaConstants.REFRESH_GRANT_TYPE),
new BasicNameValuePair(RequestEnum.STATE.getParam(), requestDto.getState()),
new BasicNameValuePair(RequestEnum.SCOPE.getParam(), requestDto.getScope()),
new BasicNameValuePair(RequestEnum.TIMESTAMP.getParam(), requestDto.getTimestamp()),
new BasicNameValuePair(RequestEnum.TOKEN_TYPE.getParam(), requestDto.getTokenType()),
new BasicNameValuePair(RequestEnum.CLIENT_SECRET.getParam(), requestDto.getClientSecret()),
new BasicNameValuePair(RequestEnum.REDIRECT_URI.getParam(), requestDto.getRedirectUri())
))
.build();

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

В нашем случае необходимо получить ФИО, дату рождения, паспортные данные и контакты.
Используем функциональный интерфейс, который поможет получать данные пользователя:

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

String personDataEntityString = esiaPersonDataFetcher.apply(ESIA_REST_API_URL + “/prns/” + esiaAccountId);

Получение контактов выглядит уже не таким очевидным, как получение данных пользователя. Для начала следует получить список ссылок на контакты:

String contactsListEntityString = esiaPersonDataFetcher.apply(ESIA_REST_API_URL + “/prns/” + esiaAccountId + “/ctts”);
EsiaListDto esiaListDto = objectMapper.readValue(contactsListEntityString, EsiaListDto.class);

Десериализуем этот список и получим объект esiaListDto. Поля из методички ЕСИА могут различаться, поэтому стоит проверить опытным путем.

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

С получением списка документов та же ситуация. Вначале получаем список ссылок на документы:

String documentsListEntityString = esiaPersonDataFetcher.apply(ESIA_REST_API_URL + “/prns/” + esiaAccountId + “/docs”);

Затем десериализуем его:

Что теперь делать со всеми этими данными?

Мы можем сделать парсинг данных и получать объекты с требуемыми полями. Здесь каждый разработчик может оформлять классы как ему необходимо, в соответствии с техническим заданием.

Пример получения объекта с необходимыми полями:

final ObjectMapper objectMapper = new ObjectMapper()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

String personDataEntityString = esiaPersonDataFetcher
.apply(ESIA_REST_API_URL + “/prns/” + esiaAccountId);

EsiaPersonDto esiaPersonDto = objectMapper
.readValue(personDataEntityString, EsiaPersonDto.class);

Заполняем объект esiaPersonDto необходимыми данными, например, контактами:

Класс EsiaPersonDto выглядит следующим образом:

Работа по усовершенствованию сервиса будет продолжаться, ведь ЕСИА не стоит на месте.

A1k89 / esia-oauth2
Goto Github
PK

View Code? Open in Web Editor

This project forked from sokolovs/esia-oauth2

Авторизация/регистрация пользователей на сайте (мобильном приложении) через сервис госуслуг. С подробной документацией step-by-step

License: BSD 2-Clause “Simplified” License

Esia-oauth2’s Introduction

  • React
  • Vue.js
    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
  • Typescript
    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
  • TensorFlow
    An Open Source Machine Learning Framework for Everyone
  • Django
    The Web framework for perfectionists with deadlines.
  • Laravel
    A PHP framework for web artisans
  • D3
    Bring data to life with SVG, Canvas and HTML. 📊📈🎉
Читайте также:  Какие новые пособия на детей будут выплачивать

Recommend Topics

  • javascript
    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
  • server
    A server is a program made to process requests and deliver data to clients.
  • Machine learning
    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

Recommend Org

  • Microsoft
    Open source projects and samples from Microsoft.
  • Google
    Google ❤️ Open Source for everyone.
  • Alibaba
    Alibaba Open Source for everyone
  • D3
    Data-Driven Documents codes.
  • Tencent
    China tencent open source team.

Предисловие

Esia-oauth2 
 Goto Github
 PK

Введение

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

  • Регистрация ИС в регистре информационных систем ЕСИА
  • Регистрация ИС в тестовой среде
  • Выполнение доработки системы для взаимодействия с ЕСИА

В данной статье будет описан только 3 пункт, предыдущие 2 – бюрократия, оставим ее за рамками Хабра. В методичке предлагают реализовать интеграцию 2 способами: SAML или OpenID Connect. Говорят,

с 01.01.2018 г. взаимодействие по протоколу SAML 2.0 больше не будет разрешено (только для действующих систем). Для подключения к ЕСИА необходимо будет использовать протокол OAuth 2.0 / OpenID Connect (сейчас доступны оба варианта).

Поэтому мы выбрали красную таблетку второй вариант. Согласно методичке, базовый сценарий аутентификации представляет собой примерно следующие шаги:

  • Система-клиент отправляет в ЕСИА запрос на аутентификацию
  • После успешной аутентификации ЕСИА возвращает ответ системе с кодом аутентификации.
  • Используя код аутентификации система получает доступ к данным пользователя

Базовая информация

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

  • КриптоПро CSP, КриптоПро .Net
  • Сертификат с закрытым ключом, полученный при регистрации ИС в реестре ИС ЕСИА (на пункте 1 из Введения)

Каждый запрос в ЕСИА по соображениям безопасности дополняется полем client_secret, которое формируется как открепленная подпись 4 полей запроса в формате UTF-8:

  • Scope (Скоуп запроса, перечень данных, которые нужно получить из ЕСИА). Например, «fullname gender email mobile usr_org»
  • Timestamp (Текущие дата и время в формате «yyyy.MM.dd HH:mm:ss +0000»)
  • ClientId (Идентификатор ИС, который выдается при регистрации системы в ЕСИА)
  • State (Идентификатор текущего запроса, каждый раз генерируется как Guid.NewGuid().ToString(«D»))

Тут SignatureProvider – класс для реализации работы с сертификатами, он довольно просто реализуется. Для подписи использовался алгоритм ГОСТ – импортозамещение и все такое.

Перенаправление в ЕСИА и аутентификация

Начнем пошаговую реализацию с пунктов 1-4: нам нужно перенаправить пользователя на сервис аутентификации ЕСИА (EsiaAuthUrl). В зависимости от среды (тестовая или продуктив) различается базовый адрес url – для тестовой среды это https://esia-portal1.test.gosuslugi.ru/aas/oauth2/ac. Полный адрес получается таким:

где RedirectUri – адрес, на который будет направлен ответ от ЕСИА, а ClientSecret – результат выполнения функции GetClientSecret. Остальные параметры описаны ранее.

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

Для получение каких-либо данных в ЕСИА нам нужно получить токен доступа. Для этого формируем POST запрос в ЕСИА (для тестовой среды базовый url такой: https://esia-portal1.test.gosuslugi.ru/aas/oauth2/te — EsiaTokenUrl). Основные поля запроса тут формируются аналогичным образом, в коде получается примерно следующее:

Некоторые статичные параметры запроса получаем из файла конфигурации (поле Configuration). Как мы можем видеть, поле code запроса заполняется значением кода аутентификации, полученным ранее. Для десериализации ответа используется следующие классы:

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

Имея токен доступа и идентификатор пользователя можно получить данные о пользователе из ЕСИА. Рассмотрим пример получения ФИО пользователя и его организации. Для этого формируем GET запрос в REST API ЕСИА, для тестового контура базовый url (EsiaRestUrl) будет таким: https://esia-portal1.test.gosuslugi.ru/rs. Токен доступа передается в заголовке запроса, сам код выглядит следующим образом:

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

Читайте также:  Новые уведомления о пособиях

Получение данных организации

Полученный токен доступа для запроса данных по организации мы использовать не можем, т.к. он завязан на определенный scope. Поэтому нужно получить отдельный токен. По сути методы получения токена доступа для организации и информации по ней не сильно отличаются от рассмотренных ранее. Для получения токена доступа мы используем идентификатор организации, код аутентификации, State предыдущего запроса на токен доступа. Новый scope формируется как список scope’ов организации, разделенных через пробел, например:

Метод получения информации по организации использует новый токен доступа и ссылку на организацию, полученную ранее вместе с данными о пользователе.

Полностью же код получения пользователя и его организации из ЕСИА выглядит так:

Заключение

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

Выберите ближайший МФЦ

Введите часть наименования или адреса:

МФЦ Ленинского района432017, Ульяновская обл, г Ульяновск, ул Гончарова, 11МФЦ Заволжского района433000, Ульяновская обл, г Ульяновск, Созидателей пр-кт, здание 17аМФЦ Засвияжского района432013, Ульяновская обл, г Ульяновск, ул Промышленная, 54ГМФЦ Железнодорожного района (Локомотивная 85)432012, Ульяновская обл, г Ульяновск, ул Локомотивная, 85МФЦ Железнодорожного района (Минаева 6)432017, Ульяновская обл, г Ульяновск, ул Минаева, 6МФЦ г.Димитровград433507, Ульяновская обл, г Димитровград, Ленина пр-кт, 16 АМФЦ Мелекесского района433505, Ульяновская обл, г Димитровград, ул Октябрьская, 64МФЦ Новомалыклинского района433560, Ульяновская обл, Новомалыклинский р-н, Новая Малыкла с, ул Кооперативная, 26МФЦ Старомайнского района433460, Ульяновская обл, Старомайнский р-н, Старая Майна рп, ул Строителей, 3МФЦ Чердаклинского района433400, Ульяновская обл, Чердаклинский р-н, Чердаклы рп, ул Советская, 7МФЦ г.Новоульяновска433300, Ульяновская обл, г Новоульяновск, ул Ульяновская, 18МФЦ Сенгилеевского района433380, Ульяновская обл, Сенгилеевский р-н, г Сенгилей, ул Красноармейская, 53МФЦ Ульяновского района433310, Ульяновская обл, Ульяновский р-н, Ишеевка рп, ул Ленина, 32МФЦ Цильнинского района433610, Ульяновская обл, Цильнинский р-н, Большое Нагаткино с, ул Куйбышева, 10МФЦ Майнского района433130, Ульяновская обл, Майнский р-н, Майна рп, ул Чапаева, 1МФЦ Тереньгульского района433360, Ульяновская обл, Тереньгульский р-н, Тереньга рп, ул Евстифеева, 3МФЦ Базарносызганского района433700, Ульяновская обл, Базарносызганский р-н, Базарный Сызган рп, Советская пл, 1МФЦ Инзенского района433030, Ульяновская обл, Инзенский р-н, г Инза, ул Труда, 28 АМФЦ Барышского района433750, Ульяновская обл, г Барыш, ул Радищева, 88 ВМФЦ Сурского района433240, Ульяновская обл, Сурский р-н, Сурское рп, ул Советская, 25МФЦ Карсунского района433210, Ульяновская обл, Карсунский р-н, Карсун рп, ул Куйбышева, 40МФЦ Вешкаймского района433100, Ульяновская обл, Вешкаймский р-н, Вешкайма рп, ул Комсомольская, 8МФЦ Кузоватовского района433760, Ульяновская обл, Кузоватовский р-н, Кузоватово рп, Заводской пер, 16МФЦ Николаевского района433810, Ульяновская обл, Николаевский р-н, Николаевка рп, Ленина пл, 3МФЦ Новоспасского района433870, Ульяновская обл, Новоспасский р-н, Новоспасское рп, ул Дзержинского, 2 ДМФЦ Павловского района433970, Ульяновская обл, Павловский р-н, Павловка рп, ул Калинина, 24МФЦ Радищевского района433910, Ульяновская обл, Радищевский р-н, Радищево рп, ул Советская, здание 34МФЦ Старокулаткинского района433940, Ульяновская обл, Старокулаткинский р-н, Старая Кулатка рп, ул Пионерская, 30ОГКУ «Правительство для граждан» (административно-управленческий персонал)432017, Ульяновская обл, г Ульяновск, ул Гончарова, 11МФЦ для бизнеса г.Ульяновск432072, Ульяновская обл, г Ульяновск, Максимова пр-д, 4МФЦ для бизнеса г.Димитровград433000, Ульяновская обл, г Димитровград, Димитрова пр-кт, 8аТОСП: г.Ульяновск, ул.Металлистов, д.16/7432031, Ульяновская обл, г Ульяновск, ул Металлистов, 16/7

Esia-oauth2 
 Goto Github
 PK

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

Что такое ЕСИА

Единая Система Идентификации и Аутентификации — российская информациия система, обеспечивающая доступ (регистрация, аутентификация) на сайты государтсвенных структур и некоторых коммерческих организаций. Подробнее на википедии

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

Сценарий авторизации выглядит примерно так:

  • Система переадресует на сайт ЕСИА
  • При успешной авторизации ЕСИА возвращает пользователя обратно на сайт и по защищенному протоколу передает его личные данные
Оцените статью