Как сформировать request?

request – обязательный параметр запроса /si-authorize. Представляет собой объект, закодированный, как строка JWT, и подписанный с помощью приватного ключа отправителя.

Json Web Token

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

  1. Спецификация rfc7519;
  2. Спецификация rfc7515;
  3. Онлайн инструмент для работы с JWT;
  4. Справочник библиотек для работы с JWT.

JWT — один из способов представления данных для передачи между двумя или более сторонами в виде JSON-объекта.

Структурно JWT состоит из трех частей:

  • header — заголовок;
  • payload — полезная нагрузка;
  • signature — подпись.

Заголовок и полезная нагрузка — обычные JSON-объекты, которые кодируются при помощи алгоритма base64url. Закодированные части соединяются друг с другом, и на их основе вычисляется подпись. Полученное значение подписи также кодируется при помощи алгоритма base64url и присоединяется к остальным частям через знак “.”.

Структура JWT

JWT = base64UrlEncode(header) + "." + base64UrlEncode(payload) + "." + base64UrlEncode(signature)

Пример формирования request на PHP

$signer = new \Lcobucci\JWT\Signer\Rsa\Sha256();
$privateKey = new
\Lcobucci\JWT\Signer\Key( file_get_contents ( getcwd () .
'/data/private.key' ));
$token = ( new \Lcobucci\JWT\Builder())->issuedBy( $clientId )
->withHeader( 'kid' , 'rsa1' )
->withClaim( 'response_type' , 'mc_si_async_code' )
->withClaim( 'client_id' , $clientId )
->withClaim( 'scope' , 'openid mc_authn' )
->withClaim( 'version' , 'mc_si_r2_v1.0' )
->withClaim( 'nonce' , Uuid:: uuid4 ()->toString())
->withClaim( 'login_hint' , 'ENCR_MSISDN:RlwdG...VkIE1ETg' )
->withClaim( 'acr_values' , '3 2' )
->withClaim( 'correlation_id' , Uuid:: uuid4 ()->toString())
->withClaim( 'client_notification_token' ,
Uuid:: uuid4 ()->toString())
->withClaim( 'aud' , 'https://idgw.mobileid.mts.ru' )
->withClaim( 'notification_uri' , 'http://' . $_SERVER [ ' HTTP_HOST']
. '/notification_uri' )
->getToken( $signer , $privateKey );
print_r ((string) $token );

Пример сформированного request

eyJhbGciOiJSUzI1NiIsImtpZCI6InJzYTEiLCJ0eXAiOiJKV1QifQ.eyJyZXNwb25zZV90eXBlIjoibWNfc2lfYXN5bmNfY29kZSIsImNsaWVudF9pZCI6Im10c190ZXN0X3NlcnZpY2UiLCJzY29wZSI6Im9wZW5pZCBtY19hdXRobiIsInZlcnNpb24iOiJtY19zaV9yMl92MS4wIiwibm9uY2UiOiIwMmJjMzA2OC03NWYzLTRiNTUtYTMyNy01NmJiYzdhMGQ4NjMiLCJsb2dpbl9oaW50IjoiRU5DUl9NU0lTRE46Umx3ZEcuLi5Wa0lFMUVUZyIsImFjcl92YWx1ZXMiOiIzIDIiLCJpc3MiOiJtdHNfdGVzdF9zZXJ2aWNlIiwiYXVkIjoiaHR0cHM6Ly9pZGd3Lm1vYmlsZWlkLm10cy5ydSIsIm5vdGlmaWNhdGlvbl91cmkiOiJodHRwczovL3NlcnZpY2UtcHJvdmlkZXIuaW8vbm90aWZpY2F0aW9uX3VyaS8iLCJjbGllbnRfbm90aWZpY2F0aW9uX3Rva2VuIjoiNTNmNGY4NWMtNGZjYS00NTRlLTkyZjUtMzk5NmU0NmYyNDZjIiwiY29ycmVsYXRpb25faWQiOiIwNWM0YWMwMi05MTQ0LTQxMWMtOTI3OS0xNjZhYzYzNzUyOGYifQ.DDsQrAvBdNVYKOpOiWoiQs1neO4LLYEuUJcPGXQOYvp9ClALTKQmGfzcONvIwVpKneWn2Gdzy-lAZMiQ44BAzC1E36GYUDUGgwLyGUgWpR1Hl3SjZCya3QReRXFG0tnGzhYoNufAWAKDUIMOES6IynjyJDrqNPvX2B-Qsfayljdwf0w3b0Ye1vK3Ao9HvbtpEuAV21zseI8q1R85Plq2ELDRKok79gjwc-q1cqCVLkaodj2XIzXJMjqPpbnu7wHtAJVwbVK6guYhdnwP6k_9_gWE0vt3kchyQT3uSEn9ZAC8hI-OafTgQq-8ZqpeHmsOGot4jFFIcSjE_sCKZHgaww

Формирование заголовка

ПараметрОписаниеОбязательныйПример
algУказание алгоритма, с помощью которого защищен JWT. Поддерживается только RS256.ДаRS256
kidИдентификатор ключа, с помощью которого выполнено формирование подписи.Значение должно совпадать с значением одноименного параметра в публичном ключе с меткой “use”:”sig”, опубликованным на jwks_endpoint.Даrsa1
typТип контента, которым является итоговый токен.Поддерживается только JWT.ДаJWT

Пример JSON.Header

{
  "alg":
 "RS256",
  "kid": "rsa1",
  "typ": "JWT"
}

Пример JWT.Header

eyJhbGciOiJSUzI1NiIsImtpZCI6InJzYTEiLCJ0eXAiOiJKV1QifQ

Формирование полезной нагрузки

ПараметрОписаниеОбязательныйПример
response_typeСценарий обработки запроса.
Единственное допустимое значение — “mc_si_async_code”.
Даmc_si_async_code
client_idИдентификатор ресурса сервис-провайдера. Выдаётся при регистрации в сервисе Мобильный ID.Значение должно совпадать со значением в одноименном параметре запроса на /si-authorize.Даmts_test_service
scopeСписок областей данных с разделителями-пробелами. Значение должно содержать “openid” и дополнительный набор областей в зависимости от подключенного тарифа.Значение должно совпадать со значением в одноименном параметре запроса на /si-authorize.Даopenid mc_authn
versionВерсия Mobile Connect API. Единственное допустимое значение — “mc_si_r2_v1.0”.Даmc_si_r2_v1.0
nonceИдентификатор для связи запроса с ID Token. 
Возвращается в составе полезной нагрузки ID Token. Значение должно быть уникальным для каждого запроса, чтобы снизить возможность атаки воспроизведения.Рекомендуемый формат UUID4. Максимум 255 знаков.
Да02bc3068-75f3-4b55-a327-56bbc7a0d863
login_hintИдентификационные данные пользователя. Допустимые значения:”ENCR_MSISDN:<base64url_encoded_encrypted_msisdn>”;”MSISDN:<end-user-msisdn>”.ДаENCR_MSISDN:RlwdG…VkIE1ETg
acr_valuesНеобходимый уровень доверия к результатам аутентификации.
Определяет группу аутентификаторов, которая может быть задействована при обработке запроса.
Поддерживается множественное значение. Указывается в порядке приоритета через пробел:2 – Seamless, PUSH-OK, USSD-OK, SMS-OTP, SMS-URL;3 – PUSH-PIN.Как правило, согласовывается при регистрации в сервисе Мобильный ID.
Да2
issИдентификатор ресурса сервис-провайдера. 
Выдаётся при регистрации в сервисе Мобильный ID. Значение должно совпадать со значением client_id.
Даmts_test_service
audБазовый URL сервиса Мобильный ID. Всегда https://idgw.mobileid.mts.ruДаhttps://idgw.mobileid.mts.ru
notification_uriHTTPS URL, куда асинхронно будет отправлен результат аутентификации пользователя.Значение должно совпадать с указанным при регистрации в сервисе Мобильный ID. Даhttps://service-provider.io/notification_uri/
client_notification_tokenСтрока, которая будет использоваться в Authorization Header как Bearer token при вызове /notification.Да53f4f85c-4fca-454e-92f5-3996e46f246c
correlation_idУникальный сквозной идентификатор для всех запросов и ответов в рамках одной транзакции.Рекомендуемый формат UUID4. Максимум 255 знаков.Нет05c4ac02-9144-411c-9279-166ac637528f
challenge_textТекст, который будет использоваться для
отображения на устройстве пользователя
в рамках аутентификационного
испытания.Допустимая длина зависит от
задействованного аутентификатора:
SIM_OK – 127 символов;
USSD_OK – 67 символов.При превышении допустимой длины
значение будет усечено справа. Параметр обязательный для запросов услуги “Авторизация” – scope: openid mc_authz
НетПодтверждаю оплату заказа
на сумму 500.00 р в Mamba со
счета телефона с Мобильным
ID 

Пример JSON.Payload

{
  "response_type": "mc_si_async_code",
  "client_id": "mts_test_service",
  "scope": "openid mc_authn",
  "version": "mc_si_r2_v1.0",
  "nonce": "02bc3068-75f3-4b55-a327-56bbc7a0d863",
  "login_hint": "ENCR_MSISDN:RlwdG...VkIE1ETg",
  "acr_values": "2",
  "iss": "mts_test_service",
  "aud": "https://idgw.mobileid.mts.ru",
  "notification_uri": "https://service-provider.io/notification_uri/",
  "client_notification_token": "53f4f85c-4fca-454e-92f5-3996e46f246c",
  "correlation_id": "05c4ac02-9144-411c-9279-166ac637528f"
}

Пример JWT.Payload

eyJyZXNwb25zZV90eXBlIjoibWNfc2lfYXN5bmNfY29kZSIsImNsaWVudF9pZCI6Im10c190ZXN0X3NlcnZpY2UiLCJzY29wZSI6Im9wZW5pZCBtY19hdXRobiIsInZlcnNpb24iOiJtY19zaV9yMl92MS4wIiwibm9uY2UiOiIwMmJjMzA2OC03NWYzLTRiNTUtYTMyNy01NmJiYzdhMGQ4NjMiLCJsb2dpbl9oaW50IjoiRU5DUl9NU0lTRE46Umx3ZEcuLi5Wa0lFMUVUZyIsImFjcl92YWx1ZXMiOiIzIDIiLCJpc3MiOiJtdHNfdGVzdF9zZXJ2aWNlIiwiYXVkIjoiaHR0cHM6Ly9pZGd3Lm1vYmlsZWlkLm10cy5ydSIsIm5vdGlmaWNhdGlvbl91cmkiOiJodHRwczovL3NlcnZpY2UtcHJvdmlkZXIuaW8vbm90aWZpY2F0aW9uX3VyaS8iLCJjbGllbnRfbm90aWZpY2F0aW9uX3Rva2VuIjoiNTNmNGY4NWMtNGZjYS00NTRlLTkyZjUtMzk5NmU0NmYyNDZjIiwiY29ycmVsYXRpb25faWQiOiIwNWM0YWMwMi05MTQ0LTQxMWMtOTI3OS0xNjZhYzYzNzUyOGYifQ

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

Формирование подписи производится с использованием приватного ключа, пара которого опубликована на jwks_endpoint и содержит указанное в заголовке JWT значение kid. При выполнении операции используется алгоритм, указанный в значении параметра заголовка “alg”.

В общем виде формирование подписи выглядит следующим образом:

Пример формирования подписи

Signature = alg(base64UrlEncode(header) + "." + base64UrlEncode(payload), 
  PRIVATE_KEY)