使用OWIN OIDC中间件调用AcquireTokenByAuthorizationCodeAsync遇JWT无效错误
解决AADSTS50027: Invalid JWT Token错误(OWIN OIDC + ADAL/MSAL场景)
嘿,我看你在搭建IdentityServer作为Azure AD和下游客户端的中间层时,卡在了调用AcquireTokenByAuthorizationCodeAsync的环节,遇到了AADSTS50027无效JWT令牌的错误——虽然身份验证流程能拿到IdToken,SecurityTokenValidated也正常触发,但授权码换令牌的步骤出了问题。结合你的代码和场景,我整理了几个核心修复点:
1. 立刻切换到MSAL库(最关键的修复)
你当前用的是ADAL(Microsoft.IdentityModel.Clients.ActiveDirectory),但你的Authority指向的是Azure AD v2.0端点(https://login.microsoftonline.com/xxx.onmicrosoft.com/v2.0)。ADAL是为v1.0端点设计的,对v2.0端点的支持有限,这大概率是导致JWT格式错误的根源。
具体操作:
- 卸载ADAL的NuGet包,安装MSAL:
Microsoft.Identity.Client(选最新稳定版就行) - 把
AuthorizationCodeReceived里的代码改成MSAL的写法:
Notifications = new OpenIdConnectAuthenticationNotifications { AuthorizationCodeReceived = async e => { // 初始化MSAL的公共客户端应用 var pca = PublicClientApplicationBuilder .Create(clientId) .WithClientSecret(clientSecret) .WithAuthority(authority) .Build(); // 这里要指定你需要从AAD获取的资源范围,比如微软Graph的默认范围,或者你自己的API范围 var result = await pca.AcquireTokenByAuthorizationCode( new[] { "https://graph.microsoft.com/.default" }, // 根据业务需求调整 e.ProtocolMessage.Code) .WithRedirectUri(redirectUri) .ExecuteAsync(); // 现在你可以拿到AAD的刷新令牌,把它和IdentityServer的用户会话关联存储起来 logger.Info($"捕获到AAD刷新令牌: {result.RefreshToken}"); logger.Info($"新的Id Token: {result.IdToken}"); } }
2. 如果暂时不能换MSAL,修正ADAL的ClientAssertion用法
如果你因为某些原因必须用ADAL,那你当前的ClientAssertion写法是错的——ADAL的ClientAssertion需要的是签名后的JWT断言,不是直接传clientId和clientSecret。正确的做法是用ClientCredential替代:
AuthorizationCodeReceived = async e => { var authContext = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext(authority); // 用ClientCredential代替ClientAssertion var credential = new ClientCredential(clientId, clientSecret); var result = await authContext.AcquireTokenByAuthorizationCodeAsync( e.ProtocolMessage.Code, new Uri(redirectUri), credential); logger.Info(result.IdToken); }
提醒:ADAL对v2.0端点的支持有很多限制,长期来看还是建议迁移到MSAL。
3. 检查Azure AD应用注册的配置细节
别忽略基础配置,这些地方也可能踩坑:
- 确认应用注册的重定向URI和代码里的
redirectUri完全一致(包括HTTP/HTTPS、端口、路径,一个字符都不能差) - 确保应用注册启用了授权码流,并且勾选了"ID令牌"和"访问令牌"的选项
- 检查Authority里的租户ID/域名是否正确,有没有写错
4. 适配IdentityServer中间层的刷新令牌验证需求
你的核心需求是捕获AAD的刷新令牌,用来验证下游客户端刷新时AAD用户的状态(比如是否被锁定或移除)。这里给你两个关键点:
- 存储AAD刷新令牌时,要和IdentityServer的用户会话绑定,比如存在数据库里关联用户ID和会话ID
- 当下游客户端请求刷新令牌时,先调用MSAL的
AcquireTokenSilent(或ADAL的AcquireTokenByRefreshTokenAsync)获取新的AAD令牌,同时调用Microsoft Graph的/me接口验证用户是否有效,再决定是否向下游签发新的令牌
内容的提问来源于stack exchange,提问作者kodbuse
相关产品推荐
相关产品推荐

