使用OpenId从Web App调用Web API时无法使用Authorize标签
.NET 4.8的Web App已通过Azure AD OpenID完成认证,可正常调用.NET 6的Web API,但为Web API控制器添加[Authorize]标签后持续出现内部错误。
Web App - Startup.cs
private static string _clientId = Properties.Resource.ClientId; private static string _aadInstance = EnsureTrailingSlash(Properties.Resource.AADInstance); private static string _tenantId = Properties.Resource.TenantId; private static string _RedirectUri = Properties.Resource.RedirectUri; private static string _clientSecret = Properties.Resource.ClientSecret; private string _authority = _aadInstance + _tenantId; private string _scope = Properties.Resource.Scope; public void ConfigureAuth(IAppBuilder app) { //Set the authentication to cookies app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType); //Create a new cookie app.UseCookieAuthentication(new CookieAuthenticationOptions()); //Set the openId connect authentication settings and call the WebPortal app in Azure app.UseOpenIdConnectAuthentication( new OpenIdConnectAuthenticationOptions { ClientId = _clientId, Authority = _authority, RedirectUri = _RedirectUri, PostLogoutRedirectUri = _RedirectUri, ClientSecret = _clientSecret, UseTokenLifetime = false, SaveTokens = true, RedeemCode = true, Scope = _scope, ResponseType = OpenIdConnectResponseType.Code, Notifications = new OpenIdConnectAuthenticationNotifications() { AuthenticationFailed = (context) => { return Task.FromResult(0); } } }); app.UseStageMarker(PipelineStage.Authenticate); }
Web API - Program.cs
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.IdentityModel.Protocols.OpenIdConnect; var builder = WebApplication.CreateBuilder(args); builder.Services.AddAuthentication(options =>{options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;options.DefaultChallengeScheme = "oidc";}).AddCookie(CookieAuthenticationDefaults.AuthenticationScheme).AddOpenIdConnect(openIdOptions =>{openIdOptions.ClientId = "7221484D-1550-4087-840D-7170BC566B93";openIdOptions.Authority = "https://login.microsoftonline.com/4c2ecc82-c268-467a-bb63-0e92247d5fab";openIdOptions.ResponseType = OpenIdConnectResponseType.Code;openIdOptions.GetClaimsFromUserInfoEndpoint = false;openIdOptions.CallbackPath = "/signin-oidc";openIdOptions.SaveTokens = true;openIdOptions.ClientSecret = "****";}); builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbucklebuilder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen(); var app = builder.Build(); // Configure the HTTP request pipeline.if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();} app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
Web API 控制器代码
[Authorize] [HttpGet("GetRoleInfo")] public async Task<IActionResult> GetRoleInfo() { try { string userId = GetAzureUserId(); List<Role> roles = await GetRoles(); List<AdminRole> adminRoles = await GetAdminRoles(); List<BusinessUser> businessUsers = await GetBusinessUsers(); List<ApplicationUser> applicationUsers = await GetApplicationUsers(); List<Application> applications = await GetApplications(); var roleAdminModel = PopulateRoleInfo(userId, roles, adminRoles, businessUsers,applicationUsers, applications); return Ok(roleAdminModel); } catch (Exception ex) { return StatusCode((int)HttpStatusCode.InternalServerError, ex.Message); } }
错误信息(翻译后)
处理请求时发生未处理的异常。InvalidOperationException: 未指定authenticationScheme,且未找到DefaultChallengeScheme。可通过AddAuthentication(string defaultScheme)或AddAuthentication(Action
configureOptions)设置默认方案。
解决方案
1. 修改Web API的认证配置为JWT Bearer
Web API作为资源服务,应验证Web App传递的Azure AD Access Token,而非使用Cookie+OIDC认证。修改Program.cs中的认证配置:
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Identity.Web; var builder = WebApplication.CreateBuilder(args); // 添加JWT Bearer认证,配置Azure AD参数 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd")); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
同时在appsettings.json中添加Azure AD配置:
"AzureAd": { "Instance": "https://login.microsoftonline.com/", "TenantId": "4c2ecc82-c268-467a-bb63-0e92247d5fab", "ClientId": "7221484D-1550-4087-840D-7170BC566B93" }
2. 确保Web App调用Web API时传递Access Token
在Web App中调用Web API时,需从认证上下文获取Access Token并在请求头中携带:
// 从OIDC保存的令牌中获取Access Token var accessToken = await HttpContext.GetTokenAsync("access_token"); // 创建HttpClient并添加Authorization头 using var client = new HttpClient(); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var response = await client.GetAsync("https://your-web-api-url/api/controller/GetRoleInfo");
3. 验证Azure AD应用注册配置
- 确认Web App的应用注册已添加对Web API应用的委托权限,并完成管理员同意。
- 确认Web API的应用注册已暴露对应的API范围,且Web App已将该范围添加到
_scope变量中。
内容的提问来源于stack exchange,提问作者Testor
相关产品推荐
相关产品推荐

