在一个 ASP.NET Core 10 项目中,基于 Controller 实现的 API 可以正常通过 PAT 进行身份认证,但基于 Minimal API 实现的 API 却认证失败
Minimal API endpoint 添加了 RequireAuthorization
public static void MapPostsOpenApis(this IEndpointRouteBuilder app)
{
var api = app.NewVersionedApi()
.MapGroup("/openapi/v{version:apiVersion}/posts")
.HasApiVersion(1)
.RequireAuthorization();
api.MapCreatePost();
}
带 PAT 的 HttpClient 请求代码如下
var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
httpClient.DefaultRequestHeaders.Add("authorization-type", "pat");
var response = await httpClient.PostAsJsonAsync(
"/openapi/v1/posts",
new { Title = "Test" , Body = "Test"});
Console.WriteLine($"Status code: {(int)response.StatusCode}({response.StatusCode})");
返回的状态码是 401(Unauthorized)
是项目中的 PolicySchemeOptions 配置代码造成 PAT 认证时使用的 authentication scheme 不对引起的
services.Configure<PolicySchemeOptions>(
CnblogsAuthenticationDefaults.AuthenticationScheme,
op =>
{
op.ForwardDefaultSelector = ctx =>
{
var authType = ctx.Request.Headers.GetOrDefault("Authorization-Type", string.Empty);
if (ctx.Request.Headers.TryGetValue(HeaderNames.Authorization, out var bearerHeader)
&& ctx.Request.Path.StartsWithSegments("/api"))
{
if (bearerHeader.FirstOrDefault()?.StartsWith("Bearer ") ?? false)
{
return string.Equals("pat", authType, StringComparison.OrdinalIgnoreCase)
? OAuth2IntrospectionDefaults.AuthenticationScheme
: "jwt";
}
}
return CookieAuthenticationDefaults.AuthenticationScheme;
};
});
将
ctx.Request.Path.StartsWithSegments("/api")
改为
ctx.Request.Path.StartsWithSegments("/api") || ctx.Request.Path.StartsWithSegments("/openapi"))
解决了