OAUTH / OIDC - 使用签名的 JWT 而不是机密进行客户端身份验证

OAUTH / OIDC - 使用签名的 JWT 而不是机密进行客户端身份验证

在我耗尽搜索精力后,我发出了信号弹。我感觉我离成功只有一步之遥,但却遇到了瓶颈。下面详细介绍了我试图完成的任务以及迄今为止采取的步骤。请指出错误并提出建议。


我有一个在 Azure 中注册的 OAUTH/OPENID/OIDC 应用程序,并且想要使用证书而不是客户端机密来验证我的客户端。


我生成了一个证书,导出并将公共部分上传到配置的“证书和机密”部分。指纹: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”:“验证”,“value”:“LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0....”,“displayName”:“L = mycity,[电子邮件保护], CN = jarred-test-oauth, OU = 联合, O = 12345”


身份验证非常简单,我能够获得授权码。我使用私有证书签署了客户端断言 JWT:

标题:{“alg”:“RS256”,“typ”:“JWT”}

有效负载:{“iss”:“2f877daa-b6f5-42a3-8430-acf238b234e1”,“sub”:“2f877daa-b6f5-42a3-8430-acf238b234e1”,“nbf”:1570803651,“exp”:1570807251,“iat”:1570803651,“jti”:“3BC87980310C490A62AA5F6343D4C55DF8EBBA85”,“typ”:“JWT”}

“iss”和“sub”是我的应用程序在Azure中的client_id。


我尝试在 Postman 中使用以下命令测试代码与令牌的交换:

邮政:https://login.microsoftonline.com/my-tenant/oauth2/v2.0/token

标头:Content-Type = application/x-www-form-urlencoded

正文:grant_type = authorization_code

code = 获得的代码

客户端断言类型 = urn:ietf:params:oauth:客户端断言类型:jwt-bearer

客户端断言 = eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIyZjg3N2RhYS1iNmY1LTQyYTMtODQzMC1hY2YyMzhiMjM0ZTEiLCJzdWIiOiIyZjg3N2RhYS1iNmY1LTQyYTMtODQzMC1hY2YyMzhiMjM0ZTEiLCJuY mYiOjE1NzA4MDM2NTEsImV4cCI6MTU3MDgwNzI1MSwiaWF0IjoxNTcwODAzNjUxLCJqdGkiOiIzQkM4Nzk4MDMxMEM0OTBBNjJBQTVGNjM0M0Q0QzU1REY4RUJCQTg1IiwidHlwIjoiSldUIn0.t8lArFodXkHO9Ps9 O3q7VH55pRl6NtcIkEbSz-hDL0V6I7iWi4N-1VBNM_nFUHkNhBoGaskV0eQtqMXYildb7oEr75KgbcjacZy2OI319uPwztHp9jVxjsBhB_rKXND4M6URr23IWkLwFb2008vq_fY4trLUZR9ILZOE0Dr_MdaQmrt8fU9 mYNkSEnRsiXKuqcS97oBfo6-9MuDbkcNuAOxZnsmbYvutk1LeabFywbc4qO3dgb8PtfqMAiYxgYTzg72tAw-ncq6uRXgG5XoxJVOExCyn5CXV9lSsE33_oekOEfRU5CyC0IvtSLhSoZ7LKtSMJ22ZXiyFqvddenJC8w


发送请求会导致 Azure(在 Postman 中)出现以下错误:

{ “error”:“invalid_request”, “error_description”:“AADSTS5002723:无效的 JWT 令牌。令牌标头中未指定证书指纹或 keyId。\r\n跟踪 ID:89f69560-9ae7-482f-803c-9faa71d44100\r\n关联 ID:e2ebab72-8b4d-47a6-85be-14893158dd5e\r\n时间戳:2019-10-11 14:23:32Z”, “error_codes”:[5002723],“timestamp”:“2019-10-11 14:23:32Z”, “trace_id”:“89f69560-9ae7-482f-803c-9faa71d44100”, “关联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://www.rfc-editor.org/rfc/rfc7523#section-2.2

微软博客 -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 Web Token (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

谢谢你!

——贾里德

答案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 到您的令牌端点。如果一切按计划进行,您应该会收到您的令牌。

相关内容