You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 23:00:01