Minimal API集成OAuth2时Swagger UI授权异常问题
背景
正在为新的Minimal API搭建认证体系,已通过GraphServiceClient成功连接Graph API。当前需完成Swagger UI的OAuth2认证配置,后续计划研究SharePoint客户端调用API的方式。
问题现象
运行Swagger并点击「Authorize」后,新标签页跳转到重定向端点,但页面一直处于加载(Pending)状态,无任何内容返回。已传入Client ID、Client Secret并选择了Scope。
OAuth2配置信息
oAuth2 (OAuth2, authorizationCode with PKCE) OAuth2.0 Auth Code Authorization URL: https://login.microsoftonline.com//oauth2/v2.0/authorize Token URL: https://login.microsoftonline.com//oauth2/v2.0/token Flow: authorizationCode with PKCE
相关代码
Swagger服务配置代码
services.ApiRequireAuthentication() .AddScoped<IUserContext, JwtUserContext>() .AddAuthorization(options => { options.AddPolicy(RoleNames.ApiAdminRole, policy => { policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme); policy.RequireRole("ApiAdmin"); }); options.AddPolicy(RoleNames.ApiAccessRole, policy => { policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme); policy.RequireRole("ApiAccess"); }); }); var apiScope = azureAd?.Scopes?.Api; if (apiScope is null || string.IsNullOrEmpty(apiScope.Scope) || string.IsNullOrEmpty(apiScope.Description)) { throw new ArgumentException("API Scope is not defined in the config."); } var authorizationUrl = $"https://login.microsoftonline.com/{azureAd?.TenantId}/oauth2/v2.0/authorize"; var tokenUrl = $"https://login.microsoftonline.com/{azureAd?.TenantId}/oauth2/v2.0/token"; services.AddEndpointsApiExplorer() .AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "SA DPC M365 API", Version = "v1" }); c.AddSecurityDefinition("oAuth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Description = $"OAuth2.0 Auth Code", Name = "oAuth2", In = ParameterLocation.Header, Flows = new OpenApiOAuthFlows { AuthorizationCode = new OpenApiOAuthFlow { AuthorizationUrl = new Uri(authorizationUrl), TokenUrl = new Uri(tokenUrl), Scopes = new Dictionary<string, string>() { { apiScope.Scope, apiScope.Description } } } } }); c.AddSecurityRequirement(new OpenApiSecurityRequirement() { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }, Scheme = "oauth2", Name = "oAuth2", In = ParameterLocation.Header }, new [] { apiScope.Scope } } }); }); }
Swagger UI配置代码
app.UseSwagger(); app.UseSwaggerUI(options => { var azureSettings = configuration.GetAzureSettings(); options.EnableTryItOutByDefault(); options.OAuthClientId(azureSettings.ClientId); options.OAuthClientSecret(azureSettings?.Credentials?.ClientSecret); options.OAuthUsePkce(); options.OAuthScopeSeparator(" "); });
解决思路及方案
1. 配置正确的重定向URI
在Azure AD应用注册的授权重定向URI列表中添加Swagger的回调地址,格式为:https://<你的API域名>/swagger/oauth2-redirect.html
本地调试时通常为 https://localhost:<端口>/swagger/oauth2-redirect.html
缺少此配置会导致Azure AD无法正确回调,引发页面Pending。
2. 移除PKCE模式下的Client Secret
PKCE授权码模式针对公共客户端设计,无需Client Secret。修改Swagger UI配置,删除Client Secret相关代码:
app.UseSwaggerUI(options => { var azureSettings = configuration.GetAzureSettings(); options.EnableTryItOutByDefault(); options.OAuthClientId(azureSettings.ClientId); // 移除该行 // options.OAuthClientSecret(azureSettings?.Credentials?.ClientSecret); options.OAuthUsePkce(); options.OAuthScopeSeparator(" "); });
保留Client Secret会破坏PKCE流程的安全性,导致授权异常。
3. 修复授权URL格式
确保生成的Authorization URL和Token URL格式正确,避免出现双斜杠//。检查azureAd.TenantId是否为空,确保拼接后的URL为:https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/authorizehttps://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token
4. 验证Scope有效性
确认apiScope.Scope是Azure AD应用注册中定义的有效API权限范围,格式通常为api://<API的Client ID>/<scope名称>。
5. 完善JwtBearer认证配置
确保ApiRequireAuthentication()内部正确配置了JwtBearer认证,指向Azure AD颁发机构:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.Authority = $"https://login.microsoftonline.com/{azureAd.TenantId}/v2.0"; options.Audience = azureAd.ClientId; // 或你的API专属Client ID });
认证中间件配置缺失或错误会影响Swagger授权流程的完整性。
内容的提问来源于stack exchange,提问作者Ben

