使用OpenIddict交换授权码获取Token时遭遇401未授权问题
问题排查与修复方案
1. 未启用Windows身份认证
你的服务配置中缺少Windows身份认证的注册逻辑,导致RequireAuthorization()无法触发正确的Windows身份验证流程。需要添加以下配置:
builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme) .AddNegotiate();
同时在应用管道中确保认证、授权中间件的顺序正确:
app.UseAuthentication(); app.UseAuthorization();
2. Token端点未处理OpenIddict请求验证
你启用了EnableTokenEndpointPassthrough(),但自定义的/token端点没有先让OpenIddict完成请求合法性校验(比如客户端凭证、授权码有效性验证),导致请求被OpenIddict中间件直接拦截返回401。正确的处理逻辑需要先完成OpenIddict的请求校验,再生成令牌:
app.MapPost("/token", async (HttpContext context) => { // 获取OpenIddict的请求对象 var request = await context.GetOpenIddictServerRequestAsync(); if (request is null) { return Results.BadRequest("无效的请求"); } // 查找并验证客户端 var applicationManager = context.RequestServices.GetRequiredService<IOpenIddictApplicationManager>(); var application = await applicationManager.FindByClientIdAsync(request.ClientId); if (application is null || !await applicationManager.ValidateClientSecretAsync(application, request.ClientSecret)) { return Results.Unauthorized(); } // 验证授权码有效性 var authorizationManager = context.RequestServices.GetRequiredService<IOpenIddictAuthorizationManager>(); var authorization = await authorizationManager.FindByTokenAsync(request.Code, OpenIddictConstants.TokenTypes.AuthorizationCode); if (authorization is null || !await authorizationManager.ValidateTokenAsync(authorization, request.Code)) { return Results.Unauthorized(); } // 生成身份标识与令牌凭证 var identity = new ClaimsIdentity(TokenValidationParameters.DefaultAuthenticationType); identity.AddClaim(OpenIddictConstants.Claims.Subject, await authorizationManager.GetSubjectAsync(authorization)); identity.SetDestinations(_ => new[] { OpenIddictConstants.Destinations.AccessToken }); var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); ticket.SetScopes(request.GetScopes()); ticket.SetResources(await context.RequestServices.GetRequiredService<IOpenIddictScopeManager>().ListResourcesAsync(request.GetScopes())); return Results.SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme); });
3. 应用注册配置不完整
你的应用注册未指定客户端类型,且包含了授权码流程不需要的权限:
await manager.CreateAsync(new OpenIddictApplicationDescriptor { ClientId = "console_app", ClientType = ClientTypes.Public, // 明确客户端类型(Postman属于公共客户端) RedirectUris = { new Uri("https://oauth.pstmn.io/v1/callback") }, Permissions = { Permissions.Endpoints.Authorization, Permissions.Endpoints.Token, Permissions.GrantTypes.AuthorizationCode, Permissions.ResponseTypes.Code // 移除Permissions.ResponseTypes.Token,授权码流程无需该权限 } });
4. 管道中间件顺序错误
确保认证、授权中间件在端点映射之前执行:
var app = builder.Build(); app.UseHttpsRedirection(); app.UseAuthentication(); app.UseAuthorization(); // 之后再映射端点 app.MapGet("/authorize", ...); app.MapPost("/token", ...); app.Run();
内容的提问来源于stack exchange,提问作者Zulander
相关产品推荐
相关产品推荐

