.Net Core 6.0 API集成Azure AD认证遭遇授权失败与CORS问题求助
从你的描述和日志来看,问题主要出在API认证方式选择错误、CORS未正确配置以及Swagger没有集成Azure AD认证支持这几个方面,下面一步步帮你解决:
1. 修正API的认证方式
你当前用的AddMicrosoftIdentityWebApp是针对传统MVC/Blazor Server这类需要浏览器跳转登录的应用的,而你的项目是Web API,应该使用专门针对API的AddMicrosoftIdentityWebApi——它基于JWT Bearer认证,更适合无状态的API场景:
修改Program.cs中的认证注册代码:
// 替换原来的AddAuthentication+AddMicrosoftIdentityWebApp builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(configuration.GetSection("AzureAd"));
2. 正确配置并启用CORS
你只调用了builder.Services.AddCors();但没有配置具体的CORS策略,也没有在请求管道中启用它。添加以下配置:
首先在服务注册部分添加CORS策略:
builder.Services.AddCors(options => { options.AddPolicy("AllowSwagger", policy => { // 开发环境允许Swagger地址跨域,生产环境建议指定具体域名 policy.WithOrigins("https://localhost:6677") .AllowAnyHeader() .AllowAnyMethod(); }); });
然后在请求管道中启用CORS,注意必须放在UseAuthentication和UseAuthorization之前:
app.UseHttpsRedirection(); // 启用CORS,放在认证逻辑之前 app.UseCors("AllowSwagger"); app.UseAuthentication(); app.UseAuthorization();
3. 配置Swagger支持Azure AD认证
要让Swagger能调用受Azure AD保护的API,需要配置Swagger集成OAuth2/OpenID Connect,这样你可以在Swagger UI中登录获取token,然后自动携带token调用接口:
修改Swagger的配置代码:
builder.Services.AddSwaggerGen(options => { options.SwaggerDoc("v1", new OpenApiInfo { Title = "Your API", Version = "v1" }); // 添加OAuth2配置 var azureAdSection = configuration.GetSection("AzureAd"); var authority = $"{azureAdSection["Instance"]}{azureAdSection["TenantId"]}"; options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = new OpenApiOAuthFlow { AuthorizationUrl = new Uri($"{authority}/oauth2/v2.0/authorize"), TokenUrl = new Uri($"{authority}/oauth2/v2.0/token"), Scopes = new Dictionary<string, string> { // 替换成你的API ClientId,格式为api://{ClientId}/access_as_user { $"api://{azureAdSection["ClientId"]}/access_as_user", "Access API as user" } } } } }); options.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } }, new[] { $"api://{azureAdSection["ClientId"]}/access_as_user" } } }); });
然后在SwaggerUI中配置OAuth客户端信息:
app.UseSwaggerUI(options => { options.SwaggerEndpoint("/swagger/v1/swagger.json", "Your API V1"); // 配置OAuth2客户端参数 var azureAdSection = configuration.GetSection("AzureAd"); options.OAuthClientId(azureAdSection["ClientId"]); options.OAuthAppName("Your API Swagger"); options.OAuthUsePkce(); });
4. 完善appsettings.json配置
确保你的AzureAd配置包含Audience字段,指定API的受众:
"AzureAd": { "Instance": "https://login.microsoftonline.com/", "Domain": "your-domain.onmicrosoft.com", "ClientId": "your-api-client-id", "TenantId": "your-tenant-id", "Audience": "api://your-api-client-id" }
最后调整中间件顺序
确保请求管道的中间件顺序符合规范:
if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseCors("AllowSwagger"); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
做完这些调整后,重启应用,打开Swagger UI,点击右上角的"Authorize"按钮,按照流程登录Azure AD获取token,之后再调用/api/User/Validate接口就可以正常访问了。
内容的提问来源于stack exchange,提问作者Ullan

