无法验证从 Azure AD 获得的访问令牌签名以保护 Web API

Posted

技术标签:

【中文标题】无法验证从 Azure AD 获得的访问令牌签名以保护 Web API【英文标题】:Unable to validate access token signature obtained from Azure AD in order to secure Web API 【发布时间】:2019-08-10 08:15:09 【问题描述】:

我正在尝试使用隐式流使用 Azure Ad 保护我的 Web api (.net core 2.2)。

我使用 Azure 门户 > Azure Active Directory > 应用程序注册 > 新应用程序注册在 Azure AD 中注册了我的应用程序:

名称 = MyWebApi

应用程序类型 = Web 应用程序/API

登录网址 = http://localhost:55000

创建此应用后,我打开其 Manifest 文件并将 oauth2AllowImplicitFlowfalse 更改为 true

这就是我在 azure 门户中为应用注册所做的一切。

然后我从我的 chrome 浏览器手动调用以下 URL 以获取 access_token:

https://login.microsoftonline.com/MY-AD-TENANT-GUID/oauth2/v2.0/authorize?client_id=MY-REGISTERED-APP-GUID&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%3A55000&scope=openid&response_mode=fragment

调用上述url得到的响应是:

http://localhost:55000/#access_token=MY-ACCESS-TOKEN&token_type=Bearer&expires_in=3600&scope=profile+openid+email+00000003-0000-0000-c000-000000000000%2fUser.Read&session_state=b2be972a-cfbc-49f1-bfc0-6c93f6c87d02

当我将授权标头中的 MY-ACCESS-TOKEN 作为不记名令牌传递给我的 Web API(.net 核心 2.2)时,我收到以下异常:

Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException:IDX10511:签名验证失败。尝试的密钥:'Microsoft.IdentityModel.Tokens.X509SecurityKey,KeyId:N-lC0n-9DALqwhuHYnHQ63GeCXc'。

然后我尝试手动验证签名:

当我将 MY-ACCESS-TOKEN 粘贴到 https://jwt.io/ 时,标题是:



  "typ": "JWT",

  "nonce": "AQABAAAAAACEfexXxjamQb3OeGQ4Gugvm6YdOT-bkA0IPllKMt06-J8If5AQ075TVCav94X_ZYcEYKaPneqdJcqYry-Z4XjX0eMN_fiJX_8wXe9D2b6eRiAA",

  "alg": "RS256",

  "x5t": "N-lC0n-9DALqwhuHYnHQ63GeCXc",

  "kid": "N-lC0n-9DALqwhuHYnHQ63GeCXc"


然后我去这个 URL 获取孩子的公钥:N-lC0n-9DALqwhuHYnHQ63GeCXc

https://login.microsoftonline.com/common/discovery/keys

然后我将以下内容作为公钥粘贴到 jwt.io 上以验证令牌签名:

-----BEGIN CERTIFICATE-----

OBTAINED-PUBLIC-KEY-FROM-THE-ABOVE-URL-HERE

-----END CERTIFICATE-----

我又得到无效签名

我去过这个帖子:https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609,但我不确定为什么我的令牌标头有 nonce 值,或者这对我来说是否是个问题。

有什么想法我在这里做错了吗?

【问题讨论】:

我看到您返回的访问令牌还包括 Microsoft Graph API 的范围。我认为这就是 Nonce 也出现的原因......并且当访问令牌意味着对于 Microsoft Graph,您将无法验证它。特别是 00000003-0000-0000-c000-000000000000/User.Read 范围。其中 00000003-0000-0000-c000-000000000000 是 Microsoft Graph API 的资源 ID。 任何想法为什么我得到 Microsoft Graph 的范围?我没有在我的请求中请求它。 在我看来,您应该更改您的应用程序以获取 API 的访问令牌。因为目前你没有指定你想要的 API。您可以将 API 注册为应用程序,对其定义 OAuth 权限,并将权限分配给获取令牌的前端应用程序。 那是最终的计划,但概念还是一样的。我已经为 API 创建了应用程序注册,并且在从 azure AD 获取其访问令牌后尝试访问该 API。问题是我猜与随机数有关,我不确定为什么我的天蓝色广告令牌在我不请求 Microsoft 图形范围时包含随机数。 很高兴看到您已经很清楚注册 API 和您所说的最终计划。另一件需要注意的事情..您从常规 Azure 门户注册了应用程序(因此默认情况下它会接受 v1 令牌)..但是您正在使用 v2 端点来获取令牌..并且您没有指定您想要的 API令牌,端点正在向您返回注册应用程序时静态定义的所有权限的令牌。我认为您的应用注册可能在当前所需权限下选择了Microsoft GraphUser.Read 【参考方案1】:

我试过这个,效果很好。

请求网址:

https://login.microsoftonline.com/tenant-name/oauth2/v2.0/authorize?client_id=application_id&response_type=token&redirect_uri=https://snv2app.azurewebsites.net&scope=api://f3d966c0-517e-4e13-a5bb-9777a916b1a0/User.read openid&response_mode=fragment

当我得到access_token后,我在jwt.io中解析并输入公钥,得到结果:

【讨论】:

Whats api://f3d966c0-517e-4e13-a5bb-9777a916b1a0/User.read 在范围内? api://f3d966c0-517e-4e13-a5bb-9777a916b1a0 是我的api和相关权限。 确实是问题所在,我的作用域不包含 API 的 URI,将其传递到作用域并没有返回 nonce 值,因此我能够验证签名。感谢您的帮助。【参考方案2】:

这里发生的是您收到的令牌是 userInfo 端点的 access_token。观众是图。图的令牌已以特殊方式修改,因此必须在验证签名之前对其进行转换。这允许图将令牌转发到下游(在转换之后),而不必担心会发生转发攻击。

验证是否'aud == graph'。

【讨论】:

我遇到了同样的麻烦,正在使用访问令牌使用 JWT.io 站点对其进行验证,但失败了,您的评论帮助我查看是否可以验证 idToken 并通过验证!但是知道如何验证访问令牌吗?我正在使用 MSAL.js 库,它使用图形范围的参数调用 acquireTokenSilent 来获取访问令牌。那么,这个graph access token有没有办法验证呢? @Maverick 你想对令牌进行什么验证? Graph 将在收到令牌时验证令牌。 我想获取他们所属的用户角色和组 您可以将令牌发送到图形以获取该信息。很难说该令牌中的内容或图形如何使用它。

以上是关于无法验证从 Azure AD 获得的访问令牌签名以保护 Web API的主要内容,如果未能解决你的问题,请参考以下文章

仅验证从 Azure B2C AD 生成的 JWT 令牌的签名 [重复]

Azure AD Msal 拦截器访问令牌

刷新的 OAuth2 令牌具有无效签名 (Azure AD OAuth2)

验证 Azure AD 令牌签名失败 JAVA

验证Azure AD令牌签名失败JAVA

Azure AD B2C 错误 - IDX10501:签名验证失败