ASP.NET Core中验证Azure DevOps OAuth生成的JWT Bearer令牌问题
Azure DevOps OAuth Token 校验问题排查
问题背景
我正在开发一个Web API项目,使用Microsoft OAuth 2.0实现身份认证,需要在Startup.cs中对认证流程返回的bearer token进行校验。校验通过后,需要使用同一个token调用Azure DevOps API。
解密后的Token载荷
{ "typ": "JWT", "alg": "RS256", "x5t": "oOvcz5M_7p-HjIKlFXz93u_V0Zo" }. { "nameid": "9f3e1329-2717-61ec-78weu-887ed4ccf1f1", "scp": "vso.agentpools_manage vso.build_execute vso.code_manage vso.dashboards_manage vso.extension_manage vso.identity vso.project_manage vso.release_manage vso.serviceendpoint_manage vso.taskgroups_manage vso.test_write vso.variablegroups_manage vso.wiki_write vso.work_full", "aui": "b021930d-1a1b-4104-890d-ebcdfccdf1ac", "appid": "bd8435c5-70d6-418a-e8923-f5595c06290c", "iss": "app.vstoken.visualstudio.com", "aud": "app.vstoken.visualstudio.com", "nbf": 1627395683, "exp": 1627399283 }.[Signature]
初始配置与问题
首次添加的鉴权代码如下,调用接口一直返回401错误:
services.AddAuthentication(options => { options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidIssuer = "app.vstoken.visualstudio.com", ValidateAudience = true, ValidAudience = "app.vstoken.visualstudio.com", ValidateIssuerSigningKey = false, IssuerSigningKey = symmetricSecurityKey }; });
核心疑问
- 由Microsoft OAuth 2.0生成的该类token是否可以自行鉴权?
- 如果可以,当前的配置遗漏了什么内容?
- 是否有其他可行的实现方案?
调整后配置与新报错
补充Authority参数后的配置如下:
.AddJwtBearer(options => { options.SaveToken = true; options.Authority = "https://app.vssps.visualstudio.com/oauth2/authorize"; options.Audience = "C00979C5-41E9-40BA-BE30-7B12D4F1D669"; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidIssuer = "app.vstoken.visualstudio.com", ValidateAudience = true, ValidAudience = "app.vstoken.visualstudio.com", ValidateIssuerSigningKey = false, IssuerSigningKey = symmetricSecurityKey }; });
调整后出现如下报错:
Content root path: D:\Projects\DevOpsSmartBoardV2\DevOpsSmartBoard\DevOpsSmartBoard fail: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[3] Exception occurred while processing message. System.InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'. ---> System.IO.IOException: IDX20807: Unable to retrieve document from: 'System.String'. HttpResponseMessage: 'System.Net.Http.HttpResponseMessage', HttpResponseMessage.Content: 'System.String'. at Microsoft.IdentityModel.Protocols.HttpDocumentRetriever.GetDocumentAsync(String address, CancellationToken cancel) at Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfigurationRetriever.GetAsync(String address, IDocumentRetriever retriever, CancellationToken cancel) at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel) --- End of inner exception stack trace --- at Microsoft.IdentityModel.Protocols.ConfigurationManager`1.GetConfigurationAsync(CancellationToken cancel) at Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler.HandleAuthenticateAsync() fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] An unhandled exception has occurred while executing the request.
问题解答
1. Token是否可自行鉴权
可以。该Token是标准的RS256加密JWT,只要配置正确的签名公钥、签发方、受众等参数,完全可以在本地完成鉴权。
2. 现有配置的错误点
- 签名校验逻辑错误:你使用了对称密钥
symmetricSecurityKey匹配非对称加密的RS256算法,完全不兼容;同时设置ValidateIssuerSigningKey = false是无效操作,JWT中间件仍会校验签名有效性,密钥不匹配自然返回401。 - Authority地址配置错误:你填写的是OAuth的授权端点,而JWT中间件需要的是OIDC元数据服务的根地址,错误的地址导致中间件无法拉取公钥等配置,触发IDX20803报错。
- 受众配置冲突:你同时在
options.Audience和TokenValidationParameters.ValidAudience中设置了不同的受众值,逻辑冲突。
3. 修复方案
本地鉴权修复代码
services.AddAuthentication(options => { options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.SaveToken = true; // 替换为正确的OIDC根地址,如果是专属组织请填写https://vssps.dev.azure.com/你的组织名/ options.Authority = "https://app.vssps.visualstudio.com/"; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = true, ValidIssuer = "app.vstoken.visualstudio.com", ValidateAudience = true, ValidAudience = "app.vstoken.visualstudio.com", ValidateIssuerSigningKey = true, // 移除自定义的symmetricSecurityKey,中间件会自动从Authority拉取微软官方公钥 ValidateLifetime = true }; });
替代实现方案
如果不想处理JWT校验的复杂配置,可以直接用收到的Token调用Azure DevOps的用户信息查询接口,接口成功返回用户信息即代表Token有效,该方案更简单,且可以复用后续调用Azure DevOps API的逻辑。
内容的提问来源于stack exchange,提问作者Akshay H
相关产品推荐
相关产品推荐

