Инструменты пользователя

Инструменты сайта


iis-info

Автор: Владимир Недорослев

Протокол работы ЕСИ

Все запросы в данном руководстве разделены построчно для удобства чтения.

Данный документ описывает конфигурацию работы ЕСИ.

Discovery document

Discovery document – это документ в формате JSON, показывающий информацию об ЕСИ - адреса Endpoint’ов, поддерживаемые scope, какую информацию о пользователе можно выдать и пр.

Его можно найти по адресу:

https://{Базовый адрес ЕСИ}/.well-known/openid-configuration  

Содержит следующие поля:

  • issuerURL идентификатор ЕСИ. ЕСИ использует его для сравнения с полем iss в ID Token’е.
  • jwks_uriURL JWK документа. Содержит ключи, которые клиенты должны использовать при проверке подписей ЕСИ.
  • authorization_endpointURL адрес Authorization Endpoint’а.
  • token_endpointURL адрес Token Endpoint’а.
  • userinfo_endpoint - URL адрес UserInfo Endpoint’а.
  • end_session_endpoint- endpoint закрытия сессии.
  • revocation_endpoint - endpoint отзыва Access Token'а.
  • scopes_supported – JSON массив, содержащий список всех значений scope, поддерживаемых ЕСИ:
    • openid – обязательный scope для всех запросов. Означает, что используется технология OpenID Connect.
    • profile – включает в себя:
      • pin - персональный номер.
      • citizenship - гражданство. Для граждан Кыргызстана KGZ.
      • name - полное имя (ФИО).
      • family_name - фамилия.
      • given_name - имя.
      • middle_name - отчество.
      • gender - пол (male или female).
      • birthdate - дата рождения в формате YYYY-MM-DD. (Например, 1990-11-23).
    • email – включает в себя email и email_verified.
    • phone – включает в себя phone и phone_verified.
    • offline_access – нужно ли получение Refresh Token'а.
    • organization_tin – ИНН юридического лица, от имени которого заходит пользователь.
      • position_name – должность пользователя в юридическом лице, указанного в organization_tin.
  • response_types_supported – JSON массив, содержащий список значений response_type, поддерживаемых ЕСИ.
  • response_modes_supported – JSON массив, содержащий список поддерживаемх response_mode, основанный на OAuth 2.0.
  • claims_supported – JSON массив, содержащий список данных, которые может выдавать ЕСИ:
    • sub – идентификатор пользователя ЕСИ.
    • pin – персональный номер.
    • family_name – Фамилия.
    • given_name – Имя.
    • middle_name – Отчество.
    • name – Полное имя (ФИО).
    • citizenship – гражданство. Для граждан Кыргызстана – KGZ.
    • gender – Пол (male или female).
    • birthdate – Дата рождения.
    • email – электронная почта.
    • email_verified – подтверждена ли почта (true/false).
    • phone_number – мобильный телефон в формате E164.
    • phone_number_verified – подтвержден ли телефон (true/false).
    • organization_tin – ИНН юридического лица, от имени которого заходит пользователь.
    • position_name – должность пользователя в юридическом лице, указанного в organization_tin.

ID Token

Для аутентификации пользователя OpenID Connect вводит понятие ID Token’а. Это структура данных, которая хранит информацию об аутентификации пользователя ЕСИ. Представляется в виде JSON Web Token (JWT). ЕСИ выдаёт ID Token со следующими полями:

  • iss – (Issuer) идентификатор ЕСИ. Это регистрозависимый URL, использующий https, содержащий схему и хост. Может содержать номер порта, путь. Не содержит параметров запроса.
  • sub – (Subject) идентификатор пользователя. Уникальный, никогда неменяющийся идентификатор пользователя, который хранит ЕСИ. Например, 24400320. Является регистрозавсимой строкой, длиной не более 255 ASCII символов.
  • aud – (Audience) массив строк, содержащий идентификаторы клиентов (client_id), которым предназначен данный ID Token.
  • exp – (Expiration) срок действия ID Token'a. Время, после которого ID Token не является валидным и не должен обрабатываться. При валидации ID Token'а текущее время должно быть до времени, указанного в этом поле. Значение представляется в виде JSON числа, показывающий количество секунд прошедших с 1970-01-01T0:0:0Z согласно UTC стандарту (см. RFC3339 для подробной информации насчёт времени в UTC).
  • iat – (Issued at) время, когда ID Token был создан. Значение представляется в виде JSON числа, показывающий количество секунд прошедших с 1970-01-01T0:0:0Z согласно UTC стандарту.
  • auth_time – (Authentication time) время, когда была произведена аутентификация пользователя. Значение представляется в виде JSON числа, показывающий количество секунд прошедших с 1970-01-01T0:0:0Z согласно UTC стандарту.
  • nonce – регистрозависимая строка, ассоциирующая сессию клиента с ID Token’ом, чтобы избежать атак повторного воспроизведения (replay attacks). Клиенты должны проверять, чтобы это значение было равно значению nonce в authentication request'e.
  • amr – (Authentication methods references) JSON массив строк, хранящий методы аутентификации, использованные при аутентификации пользователя. Например, может покаазть, что при аутентификации был использован пароль и OTP. Возможные значения: eid (Паспорт), pwd (Логин/пароль), cds (Облачная ЭП).
  • at_hash – хэш Access Token’а. Хэш вычисляется по левой половине хэшей октетов Access Token“a в формате ASCII. Примененный хэш-алгоритм указан в головной части (header) ID Token’a в значении alg.

Authentication request

Authentication request (Запрос на аутентификацию) — это GET или POST запрос клиента в Authorization Endpoint, который требует, чтобы пользователь аутентифицировался в ЕСИ.

В случае GET запроса, параметры запроса указывается непосредственно в самом запросе.
В случае POST запроса, параметры запроса указываются в теле запроса (Content-Type: application/x-www-form-urlencoded)

Параметры запроса

  • scope (Обязательный) – разделенные пробелом значения, показывающие, какие данные необходимы клиенту. Обязательно должно содержать значение openid.
  • response_type (Обязательный) – определяет способ процесса авторизации. В случае с ЕСИ используется значение code.
  • client_id (Обязательный) – идентификатор клиента, выданный ЕСИ.
  • redirect_uri (Обязательный) – URI, куда будет отправлен ответ ЕСИ после того, как пользователь пройдёт аутентификацию в ЕСИ. Он задаётся вместе с client_id при регистрации клиента.
  • nonce (Опциональный) – регистрозависимая строка ассоциирующая сессию клиента с ID Token’ом, чтобы избежать атак повторного воспроизведения (replay attacks).
  • state (Опциональный) – значение для сохраниния состояние между запросом и callback’ом. Обычно для борьбы с CSRF это значение криптографически привязывается к куки браузера.

PKCE

Так как ЕСИ использует Authorization Code flow with PKCE (RFC7636), при запросе на аутентификацию необходимо дополнительно сделать следующее:

  • Сформировать и сохранить code_verifier (он ещё понадобится при запросе на получение токенов) - криптографически случайная строка размером от 43 до 128 символов, и состоящая из символов a-z A-Z 0-9 -._~
  • Сформировать code_challenge следующим образом:
base64url(sha256(code_verifier))
  • Добавить в запрос следующие параметры:
&code_challenge={сформированный code_challenge}
code_challenge_method=S256

Валидация запроса

При получении запроса на аутентификацию ЕСИ проверит, чтобы все параметры запроса соответствовали стандарту OAuth 2.0 и OpenId Connect. Подразумевается наличие обязательных параметров scope, response_type, client_id, redirect_uri. В случае, если запрос составлен не верно, ЕСИ вернёт ошибку на указанный redirect_uri. Информация об ошибке будет представлена в виде параметров.

Возможны следующие параметры:

  • error (Обязательный) – название ошибки. Может принимать следующие значения:
    • invalid_request – неправильный запрос. Возникает, если в запросе отсутствует обязательный параметр, запрос содержит неправильное значение параметра, включает в себя одинаковый параметр более одного раза и пр.
    • unauthorized_client – неавторизованный клиент. Клиент не авторизован и не может получить авторизационный код.
    • access_denied – отказано в доступе. Пользователь либо ЕСИ отколнили запрос.
    • unsupported_response_type – неподдерживаемый возвращаемый тип. ЕСИ не поддерживает получение авторизационного кода указанным методом.
    • invalid_scope – неправильный scope. Запрашиваемое(-ые) значения scope неверны, неизвестны, либо составлены неправильно.
    • server_error – ошибка сервера. Ошибка со стороны ЕСИ, которая не позволяет обработать запрос.
    • temporarily_unavailable – временно недоступно. В данный момент ЕСИ не может обработать запрос из-за перегрузки либо технических работах на сервере.
    • invalid_request_uri – неправильный redirect_uri. redirect_uri возвращает ошибку при перенаправлении либо содержит неправильные данные.
  • error_description (Опциональный) – описание ошибки понятное человеку.
  • error_uri (Опциональный) – URI веб-страницы, на которой находится дополнительная информация об ошибке.
  • state (Опциональный) – состояние согласно OAuth 2.0. Ставится значение, полученное от клиента.

Примеры

Примеры значений scope:

scope=openid profile email
scope=openid profile notification_api phone

Пример ответа клиента, который перенаправляет браузер пользователя к Authorization endpoint для запроса на аутентификацию:

302 Found
Location: https://{базовый-адрес-ЕСИ}/connect/authorize?
  response_type=code
  &scope=openid%20profile%20email
  &client_id=s6BhdRkqt3
  &state=af0ifjsldkj
  &redirect_uri=https://client.example.org/cb
  &code_challenge=UTGRtxSHqyGSX1z54iTOBB6Z3WdAMeFv7iYSC6yqx0w
  &code_challenge_method=S256

Пример запроса, который отправит браузер пользователя к ЕСИ в ответ на redirect ответ клиента:

GET https://{базовый-адрес-ЕСИ}/connect/authorize?
  response_type=code
  &scope=openid%20profile%20email
  &client_id=s6BhdRkqt3
  &state=af0ifjsldkj
  &redirect_uri=https://client.example.org/cb 
  &code_challenge=UTGRtxSHqyGSX1z54iTOBB6Z3WdAMeFv7iYSC6yqx0w
  &code_challenge_method=S256

Пример ошибки:

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
  error=invalid_request
  &error_description=Unsupported%20response_type%20value
  &state=af0ifjsldkj

Пример ответа ЕСИ при успешной валидации запроса на аутентификацию:

HTTP/1.1 302 Found
Location: https://client.example.org/cb?
  code=SplxlOBeZQQYbYS6WxSbIA
  &state=af0ifjsldkj

Token request

Для получения ID Token’а и Access Token’а клиент должен отправить POST запрос в Token Endpoint ЕСИ, предоставив полученный авторизационный код (code), свой client_id, client_secret и redirect_uri.

client_id и client_secret должны находится в заголовке запроса Authorization типа Basic в качестве имени пользователя и пароля соответственно.

В теле запроса должны находится следующие параметры (Content-Type: application/x-www-form-urlencoded):

grant_type=authorization_code
&code={ваш авторизационный код}
&redirect_uri={ваш redirect_uri}
&code_verifier={code_verifier, который вы сгенерировали на этапе Authentication request}

Пример запроса к Token Endpoint

POST https://{базовый-адрес-ЕСИ}/connect/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https://client.example.org/cb
&code_verifier=oV0CFtgI2ywyqV6y5Z2gy49stoKn0T2daY_nLvXDeWRNqQeJ

Валидация запроса

ЕСИ валидирует запрос следующим образом:

  1. Аутентифицирует клиента по полученным client_id и client_secret.
  2. Проверит авторизационный код. Действительно ли он был выдан данному клиенту. Правильный ли он, не был ли он использован до этого, был ли выдан в результате запроса на аутентификацию.
  3. Сравнит полученный redirect_uri со значением redirect_uri полученном при запроса на аутентификацию.
  4. Сформирует code_challenge из полученнго code_verifier и сравнит с ранее полученным code_challenge при запросе на аутентификацию.

При успешной валидации ЕСИ вернёт Id Token и Access Token в ответ в формате application/json, а также следующие поля:

  • token_type – по стандарту всегда имеет значение Bearer.
  • refresh_token – токен, позволяющий получить новый access token после того, как он истёк. Выдаётся в случае, если было указано значение scope offline_access во время authentication request.
  • expires_in – значение в секундах, показывающее через сколько access token станет недействительным.

При возникновении ошибки, информация о ней вернётся в том же формате, что и при запросе на аутентификацию.

Пример успешного ответа ЕСИ с ID Token'ом и Access Token'ом:

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{
 "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImNhZzBDYk1UYzh4d293MDVaVDRpRFEiLCJ0eXAiOiJhdCtqd3QifQ.eyJuYmYiOjE1ODQ0NDExNTAsImV4cCI6MTU4NDQ0NDc1MCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo3MDAwIiwiYXVkIjoibm90aWZpY2F0aW9uX2FwaSIsImNsaWVudF9pZCI6Im12Yy1jbGllbnQiLCJzdWIiOiIxMDAwMDAwIiwiYXV0aF90aW1lIjoxNTg0NDQxMTQ4LCJpZHAiOiJsb2NhbCIsInNjb3BlIjpbInByb2ZpbGUiLCJvcGVuaWQiLCJlbWFpbCIsInBob25lIiwibm90aWZpY2F0aW9uX2FwaSJdLCJhbXIiOlsibWZhIl19.KC-_Ua4k3rbRAVEkWF_NffnlGqInfSsSiD-zEk5dmLn5a7PAiiptDNqGpmSJbMhl2rbyFqTrBtUDxmkSbXALDWTAvuRqagTkEvlu2uUpJSQ9c_aYLsW4QdUdR2uAKliRlNAQFygWkN4xsXPSaB6E0B71YKmQcYutssBBcP3tBu_E4EDMW30Vky_osQeB8moHkPthMxXkpBxLSKieY77FOQDJzbaVmzrm9wmIor7OuwFtp0b9yKdpAsg9cGbgcmqW5pYNSa2GdhEzYrf6tkfF7tyuw-LYbJjCklfPwIQNk-RT1TicSwdZzsBWoAS8pWiBfwN4MAaA6TP4O6LA7hcdZw",
 "token_type": "Bearer",
 "refresh_token": "8xLOxBtZp8",
 "expires_in": 3600,
 "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6ImNhZzBDYk1UYzh4d293MDVaVDRpRFEiLCJ0eXAiOiJKV1QifQ.eyJuYmYiOjE1ODQ0NDExNTAsImV4cCI6MTU4NDQ0MTQ1MCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo3MDAwIiwiYXVkIjoibXZjLWNsaWVudCIsIm5vbmNlIjoiNjM3MjAwMzc5MzYyNjEzMzE0LlkyTmtZVGN3T0dFdFl6Y3pNaTAwTURreUxUbGhPVFF0T0RJd1pXVmxPVGMxTURVeFpXUTJNemd3TXpJdE9XTmlZaTAwWVROakxUZzFaREV0WkdFMU1XVTJNbVJsWVRFNCIsImlhdCI6MTU4NDQ0MTE1MCwiYXRfaGFzaCI6ImhpOWItMURYanVtSWRCeFJ1VGRlb3ciLCJzX2hhc2giOiJFNXdOMzRlMFZkVl9jSVJQREZGS0h3Iiwic2lkIjoiMjc1SEtZRE1QS0EtRGt1NXJWdjNJdyIsInN1YiI6IjEwMDAwMDAiLCJhdXRoX3RpbWUiOjE1ODQ0NDExNDgsImlkcCI6ImxvY2FsIiwiYW1yIjpbIm1mYSJdfQ.dkcyzcRHrTZAGATA2p3Q8x7PMeQRQdWYq9h0ptMD0lx_2LvKNc9ItEncBFm1Kjjtq8oY2wiIGILJTBwiyO7IGCePHCLLXTy2csxcd-gL83nXL5aosIOxOjTiIc7Wo4mCVIsnk-fHdroHmfPmB-gAEAnoEpOTbN5IZ-lpAJl_WhB-utbiNVyEVrzm03usHppbu2-ev-9vWOuiQy6Ryg-GBWTkv0Hi3Q5mnG1FBA-ac-13JXBIhSEPtKWFw6Ck3-OVi4IoTzh5uz-IPFv_1H12ervVE7Qf9tv6sEbrGj2q1x3KbAkAEeaGpJWduJfHLNthxwk99Gbl8JL710cZGGCpdQ"
}

UserInfo request

Для получения информации о пользователе, клиенту необходимо отправить GET или POST запрос в UserInfo Endpoint с заголовком Authorization типа Bearer со значением полученного Access Token'а.

Рекомендуется использовать GET запрос.

Пример запроса:

GET https://{базовый-адрес-ЕСИ}connect/userinfo 
Host: server.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImNhZzBDYk1UYzh4d293MDVaVDRpRFEiLCJ0eXAiOiJhdCtqd3QifQ.eyJuYmYiOjE1ODQ0NDExNTAsImV4cCI6MTU4NDQ0NDc1MCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo3MDAwIiwiYXVkIjoibm90aWZpY2F0aW9uX2FwaSIsImNsaWVudF9pZCI6Im12Yy1jbGllbnQiLCJzdWIiOiIxMDAwMDAwIiwiYXV0aF90aW1lIjoxNTg0NDQxMTQ4LCJpZHAiOiJsb2NhbCIsInNjb3BlIjpbInByb2ZpbGUiLCJvcGVuaWQiLCJlbWFpbCIsInBob25lIiwibm90aWZpY2F0aW9uX2FwaSJdLCJhbXIiOlsibWZhIl19.KC-_Ua4k3rbRAVEkWF_NffnlGqInfSsSiD-zEk5dmLn5a7PAiiptDNqGpmSJbMhl2rbyFqTrBtUDxmkSbXALDWTAvuRqagTkEvlu2uUpJSQ9c_aYLsW4QdUdR2uAKliRlNAQFygWkN4xsXPSaB6E0B71YKmQcYutssBBcP3tBu_E4EDMW30Vky_osQeB8moHkPthMxXkpBxLSKieY77FOQDJzbaVmzrm9wmIor7OuwFtp0b9yKdpAsg9cGbgcmqW5pYNSa2GdhEzYrf6tkfF7tyuw-LYbJjCklfPwIQNk-RT1TicSwdZzsBWoAS8pWiBfwN4MAaA6TP4O6LA7hcdZw

Ответ от ЕСИ:

Если пользователь заходит как физическое лицо:

HTTP/1.1 200 OK
Content-type: application/json
{
  "sub":"1000000",
  "pin":"20101199012345",
  "citizenship":"KGZ",
  "family_name":"Андреев",
  "given_name":"Андрей",
  "middle_name":"Андреевич",
  "name":"Андреев Андрей Андреевич",
  "gender":"male",
  "birthdate":"1990-01-01",
  "email":"some.email@gmail.com",
  "email_verified":"True",
  "phone_number":"+996000123456",
  "phone_number_verified":"True"
}

Если пользователь заходит как юридическое лицо:

HTTP/1.1 200 OK
Content-Type: application/json
{
   "sub": "1000000",
   "organization_tin": "ОсОО \"/Компания\"",
   "position_name": "Директор",
   "pin":"20101199012345",
   "citizenship":"KGZ",
   "family_name":"Андреев",
   "given_name":"Андрей",
   "middle_name":"Андреевич",
   "name":"Андреев Андрей Андреевич",
   "gender":"male",
   "birthdate":"1990-01-01",
   "email":"some.email@gmail.com",
   "email_verified":"True",
   "phone_number":"+996000123456",
   "phone_number_verified":"True"
}
iis-info.txt · Последние изменения: 2020/12/21 11:14 — admin1