如何配置具有OAuth2授权的ASP.NET Core 6 Web API以使用openid系统的jwks端点来验证访问令牌?
当我“手动”验证声明时,我的API可以很好地与oauth2一起工作,但失败了http 401未经授权的响应头WwwAuthenticate:
Bearer error=“invalid_token”,error_description=“未找到签名密钥”
我使用Microsoft.AspNetCore.Authentication.JwtBearer v6.0.20
。我认为问题在于ID令牌有一个签名密钥ID,但在Access令牌上为null:
根据拥有openid的团队(我在公司环境中),系统符合“pingfederate”,并且通过设计签名密钥不存在。
他们建议我使用jwks端点来验证访问令牌,但我不知道如何在.NET中配置它
我的程序.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();
...
如果我使用AuthorizeAttribute
,它会因为签名密钥丢失错误而失败,但是如果我“手动”验证声明,它会正常工作:
//[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());
}
我可以看到访问令牌是以“承载xxx”格式传递的
1条答案
按热度按时间hjqgdpho1#
我遵循这个solution并使用
IdentityModel.AspNetCore.OAuth2Introspection
pkg唯一的区别是我不能使用AddJwtBearer,因为它给了我一个
InvalidOperationException
:方案已存在:承载
然后使用AddOAuth2Introspection,一切都像魔法一样工作: