OAUTH / OIDC - аутентификация клиента с использованием подписанного JWT вместо секрета

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


У меня есть приложение OAUTH / OPENID / OIDC, зарегистрированное в Azure, и я хочу использовать сертификат для аутентификации моего клиента вместо секретного кода клиента.


Я создал сертификат, экспортировал и загрузил общедоступную часть в раздел конфигурации «сертификаты и секреты». Отпечаток: 3BC87980310C490A62AA5F6343D4C55DF8EBBA85

Манифест с измененными значениями ...

"keyCredentials": [ { "customKeyIdentifier": "3BC87980310C490A62AA5F6343D4C55DF8EBBA85", "endDate": "2020-10-10T19: 45: 00Z", "keyId": "ff3ce8e8-7268-4b46-88be-d3a191a0695e", "startDate": "2019-10-10T19: 45: 00Z", "type": "AsymmetricX509Cert", "usage": "Подтвердить", "значение": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0 ....", "displayName": "L = mycity, (скрытый) CN = jarred-test-oauth, OU = Federation, O = 12345"


Аутентификация достаточно проста и я могу получить код авторизации. Я подписал JWT утверждения клиента с помощью частного сертификата:

Заголовок: { "alg": "RS256", "тип": "JWT" }

Полезная нагрузка: { "iss": "2f877daa-b6f5-42a3-8430-acf238b234e1", "sub": "2f877daa-b6f5-42a3-8430-acf238b234e1", «НБФ»: 1570803651, «exp»: 1570807251, «iat»: 1570803651, «jti»: «3BC87980310C490A62AA5F6343D4C55DF8EBBA85», "тип": "JWT" }

"iss" и "sub" - это client_id моего приложения в Azure.


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

POST: https: //login.microsoftonline.com/my-tenant/oauth2/v2.0/token[1290 visibleHeaders: Content-Type = application / x-www-form-urlencoded

Тело: grant_type = authorization_code [тысяча двести девяносто-две] код = obtained_code

client_assertion_type = урна: IETF: PARAMS: OAuth: клиент-утверждение типа: JWT-носителем

client_assertion = eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIyZjg3N2RhYS1iNmY1LTQyYTMtODQzMC1hY2YyMzhiMjM0ZTEiLCJzdWIiOiIyZjg3N2RhYS1iNmY1LTQyYTMtODQzMC1hY2YyMzhiMjM0ZTEiLCJuYmYiOjE1NzA4MDM2NTEsImV4cCI6MTU3MDgwNzI1MSwiaWF0IjoxNTcwODAzNjUxLCJqdGkiOiIzQkM4Nzk4MDMxMEM0OTBBNjJBQTVGNjM0M0Q0QzU1REY4RUJCQTg1IiwidHlwIjoiSldUIn0.t8lArFodXkHO9Ps9O3q7VH55pRl6NtcIkEbSz-hDL0V6I7iWi4N-1VBNM_nFUHkNhBoGaskV0eQtqMXYildb7oEr75KgbcjacZy2OI319uPwztHp9jVxjsBhB_rKXND4M6URr23IWkLwFb2008vq_fY4trLUZR9ILZOE0Dr_MdaQmrt8fU9mYNkSEnRsiXKuqcS97oBfo6-9MuDbkcNuAOxZnsmbYvutk1LeabFywbc4qO3dgb8PtfqMAiYxgYTzg72tAw-ncq6uRXgG5XoxJVOExCyn5CXV9lSsE33_oekOEfRU5CyC0IvtSLhSoZ7LKtSMJ22ZXiyFqvddenJC8w


Отправка запроса приводит к следующей ошибке от Azure (в почтальоне):

{ "error": "invalid_request", "error_description": "AADSTS5002723: Недействительный токен JWT. В заголовке токена не указаны ни отпечаток сертификата, ни идентификатор ключа. \ r \ nИдентификатор трассировки: 89f69560-9ae7-482f-803c-9faa71d44100 \ r \ nИдентификатор корреляции: e2ebab72-8b4d-47a6- 14893158dd5e \ r \ nTimestamp: 2019-10-11 14: 23: 32Z ", "error_codes": [ 5002723 ], "timestamp": "2019-10-11 14: 23: 32Z", "trace_id": "89f69560-9ae7-482f-803c-9faa71d44100", "correlation_id": "e2ebab72-8b4d-47a6-85be-14893158dd5e" }

Я предполагаю, что заголовок должен содержать значение KID или «отпечаток пальца». У меня нет KID, поскольку я не настраиваю для этой цели общедоступный JWKS и не уверен, что вводить в качестве поля для отпечатка пальца.


Очень признателен, если кто-нибудь сможет указать мне правильное направление. Я уже видел все ссылки на других, которые задавали вопросы. Я действительно мог бы попросить кого-нибудь, кто знает, что делать дальше.


Вот некоторые инструменты и документы, которые помогли мне продвинуться так далеко:

Инструмент подписи JWT - http://kjur.github.io/jsjws/tool_jwt.html

Объяснение аутентификации клиента Oauth - https://medium.com/@darutk/oauth-2-0-client-authentication-4b5f929305d4

RFC 7523 Профили утверждений OAuth JWT - https://tools.ietf.org/html/rfc7523 # section-2.2

Блог Microsoft - https://blogs.msdn.microsoft.com/exchangedev/2015/01/21/building-daemon-or-service-apps-with-office-365-mail -calendar-and-contacts-apis-oauth2-client-credential-flow /

Веб-токен JSON (JWT) - заявки и подпись draft-jones-json-web-token-01 - https://tools.ietf.org/id/draft-jones-json-web-token-01.html

КБ для аутентификации клиента - https://kb.authlete.com/en/s/oauth-and-openid-connect/a/client-secret-jwt

Спасибо!

- Джарред

0
задан 11 October 2019 в 17:54
1 ответ

Пришлось запаниковать, прежде чем найти ответ. 5 дней поиска и вот мои выводы на тот случай, если кто-то еще найдет этот вопрос и ему понадобится помощь.

Быстрые шаги:

  1. Создайте свой закрытый ключ (ниже используется PowerShell)

  2. Создайте свой открытый сертификат

  3. Преобразуйте свой открытый сертификат и закрытый ключ в формате PEM

  4. Загрузите свой открытый сертификат в конфигурацию приложения в разделе «Сертификаты и секреты»

  5. Получите отпечаток вашего сертификата в Base64 (либо захватите при создании сертификата, либо найдите в хранилище ключей или в другом месте)

$cert=New-SelfSignedCertificate -Subject "CN=$ApplicationName" -CertStoreLocation "Cert:\CurrentUser\My"  -NotAfter (Get-Date).AddMonths(24) -KeyExportPolicy Exportable -KeySpec Signature
$bin = $cert.RawData
$base64Value = [System.Convert]::ToBase64String($bin)
$bin = $cert.GetCertHash()
$base64Thumbprint = [System.Convert]::ToBase64String($bin)
  1. создайте свой JWT (Я использовал https://jwt.io/ )

Заголовок

{
  "alg": "RS256",
  "typ": "JWT",
  "x5t": "<Base64 Thumbprint>"
}

Полезная нагрузка

{
  "iss": "<clientid>",
  "sub": "<clientid>",
  "exp": 1570838377 (expiration time),
  "jti": "<random unique identifier>",
  "aud": "https://<token-endpoint>"
}

Поместите ваш закрытый ключ (PEM) в нижний верификатор, который подпишет ваш JWT в " Закодированное "окно".

  1. Получите код авторизации
  2. Создайте запрос на токены

Заголовок

Content-Type: application/x-www-form-urlencoded

Тело

grant_type=authorization_code
code=OAQABAAIAAACQN9QBR.... (your authorization code)
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer
client_assertion=eyJhbGciOiJSUzI1NiIsInR5.... (your signed JWT)
state=state (optional)
redirect_uri=https%3A%2F%2Fblackhole.com (The callback URI)
  1. POST на конечную точку вашего токена. Если все пойдет по плану, вы должны получить свои токены.
0
ответ дан 5 December 2019 в 00:28

Теги

Похожие вопросы