我有一个需要使用 AzureAD 保护的 API,以便它可以使用 SSO。
API 有一个 Swagger UI,所以我有(在阅读了很多很多教程/解释/问题之后):
- 在 Azure 中创建应用注册
- 为我的 API 创建了一个范围
- 将我的范围添加为 API 权限
- 将清单中的“accessTokenAcceptedVersion”更改为 2
- 设置 Swagger 以使用具有适当配置和值的 OAuth2 流
- 使用 Microsoft.Identity.Web 设置 API 并添加配置以允许登录到单个租户
根据:https ://github.com/AzureAD/microsoft-identity-web/wiki/web-apis,API中的设置如下:
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration, subscribeToJwtBearerMiddlewareDiagnosticsEvents: true);
appsettings.json:
{
...
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "{guid for tenant ID from Azure portal}",
"ClientId": "{guid for client ID from Azure portal}",
"CallbackPath": "/signin-oidc",
"SignedOutCallbackPath ": "/signout-callback-oidc"
}
}
我现在大摇大摆地拥有授权按钮。
当我单击按钮时,我得到一个对话框:
输入客户端ID,选择范围并单击授权。Azure AD 登录窗口在新选项卡中打开,输入凭据并提交,然后我们被重定向回 swagger,我们被授权:
到现在为止还挺好。
然后我尝试调用 API 本身,但失败并显示 401。
检查请求,我可以看到 JWT 令牌作为不记名令牌传递。
所以我在 JwtBearerMiddlewareDiagnostics 中设置了一些断点来尝试找出问题所在。
以下事件按以下顺序触发:
OnMessageReceivedAsync
OnTokenValidatedAsync
- 与IsAuthenticated
:真OnChallengeAysnc
- 带有IsAuthenticated
:false 和AuthenticationFailure
:null
作为比较,如果我让 JWT 过期,我会得到:
OnMessageReceivedAsync
OnAuthenticationFailedAsync
- 与IsAuthenticated
:假OnChallengeAsync
- 带有IsAuthenticated
:false 和AuthenticationFailure
:“关于令牌过期的一些消息”
因此,我正在努力解决的问题是,当我的 JWT 有效时,OnTokenValidatedAsync 会触发并显示有效的 UserPrinciple,其中 Identity 表明用户已通过验证。但几乎在此之后,会立即触发身份验证挑战,其中 UserPrinciple 显示用户未经过验证......然后由于我没有处理 OnChallengeAsync 事件,因此返回 401。我的理解是,如果没有有效令牌(在 JWT 流中),则会调用 OnChallengeAsync,但调用 OnTokenValidatedAsync 表明令牌已正确传递并且用户有效?!
此外,当我遇到“有效失败”(令牌已过期)时,传递给的上下文OnChallengeAsync
清楚地显示了AuthenticationFailure
属性中的原因,但是当OnChallengeAsync
我(据我所知)好的令牌触发时,AuthenticationFailure
为空......