ASP.NET Core 6 Web API OAuth2授权:JWKS验证AccessToken签名密钥缺失
我正在配置带有OAuth2授权的ASP.NET Core 6 Web API,目标是通过OpenID系统的JWKS端点验证AccessToken。目前手动验证Claims的接口可正常运行,但使用[Authorize]特性时,接口会返回HTTP 401未授权,响应头的WwwAuthenticate字段提示:
Bearer error="invalid_token",error_description="The signature key was not found"
我使用的是Microsoft.AspNetCore.Authentication.JwtBearer v6.0.20,排查发现ID Token包含签名密钥ID(kid),但AccessToken的kid为空。负责OpenID的团队表示该系统符合PingFederate规范,这是设计使然,建议通过JWKS端点验证AccessToken,但我不知道如何在.NET中进行相应配置。
以下是Program.Main的精简代码:
var builder = WebApplication.CreateBuilder(args); var config = builder.Configuration; ... builder.Services.AddSwaggerGen(opt => { opt.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = new OpenApiOAuthFlow { AuthorizationUrl = new Uri($"{config.GetValue<string>("authority")}/authorization"), TokenUrl = new Uri($"{config.GetValue<string>("authority")}/token") } } }); opt.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Id = "oauth2", Type = ReferenceType.SecurityScheme } }, new string[]{ } } }); }); builder.Services.AddAuthentication(authOpt => { authOpt.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, opt => { opt.Authority = config.GetValue<string>("authority"); opt.MetadataAddress = $"{config.GetValue<string>("authority")}/.well-known/openid-configuration"; opt.Audience = "myapp"; }); builder.Services.AddAuthorization(auth => { auth.AddPolicy("canread", pol => pol.RequireClaim("scope", "read:weather")); }); var app = builder.Build(); app.UseSwagger(); // configure swagger ui auth option app.UseSwaggerUI(opt => { opt.OAuthAppName("my app"); opt.OAuthClientId(config.GetValue<string>("clientid")); opt.OAuthClientSecret(config.GetValue<string>("clientsecret")); opt.OAuthAdditionalQueryStringParams(new Dictionary<string, string> { { "audience", "myapp" } }); opt.OAuthScopeSeparator(" "); opt.OAuthUsePkce(); }); ... // custom middleware to inspect access token is passed app.UseMiddleware<MessageInspector>(); app.UseAuthentication(); app.UseAuthorization(); ...
添加[Authorize]特性会触发签名密钥缺失错误,但以下手动验证Claims的接口可正常运行:
//[Authorize] //[Authorize("canread", AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] [HttpGet(Name = "GetWeatherForecast")] public ActionResult<IEnumerable<WeatherForecast>> Get() { var tokenStr = HttpContext.Request.Headers.Authorization.FirstOrDefault(); var handler = new JwtSecurityTokenHandler(); // auth token is in form "Bearer abcdefg1234567890..." var jwt = handler.ReadJwtToken(tokenStr.Remove(0, 7)); if (!jwt.Claims.Where(x => x.Type == "scope" && x.Value == "read:weather").Any()) { return StatusCode(401); } return Ok(Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = Random.Shared.Next(-20, 55), Summary = Summaries[Random.Shared.Next(Summaries.Length)] }) .ToArray()); }
已确认AccessToken是以"Bearer xxx"格式传递的。
内容的提问来源于stack exchange,提问作者Jason
相关产品推荐
相关产品推荐

