.NET 7 Web API迁移后本地启动遇provider字段必填认证错误
问题:迁移到.NET 7 Web API后Azure认证接口返回400错误
迁移原.NET 5应用到.NET 7 Web API后,本地调用POST http://localhost:5000/api/Authentication/login接口返回400 Bad Request,错误信息如下:
{"errors":{"provider":["The provider field is required."]},"type":"https://tools.ietf.org/html/rfc7231#section-6.5.1", "title":"One or more validation errors occurred.","status":400,"traceId":"00-[...]-00"}
现有配置
appsettings.json配置
{ "AllowedHosts": "*", "Authentication": { "Azure": { "AADInstance": "https://login.microsoftonline.com/", "CallbackPath": "/signin-oidc" } } }
Program.cs服务配置
// ------------ // Configure Services // ------------ string? connectionString = builder.Configuration.GetConnectionString("SqlServerConnection"); var configuration = builder.Configuration; // Identity builder.Services.AddIdentity<User, Role>() .AddEntityFrameworkStores<AppDbContext>() .AddDefaultTokenProviders(); // Authentication var clientId = configuration.GetValue<string>("Authentication:Azure:ClientId"); if (clientId == null) throw new System.Configuration.ConfigurationErrorsException("Missing Azure configuration"); builder.Services.AddAuthentication() .AddOpenIdConnect( options => { options.ClientId = configuration.GetValue<string>("Authentication:Azure:ClientId"); options.ClientSecret = configuration.GetValue<string>("Authentication:Azure:ClientSecret"); options.Authority = $"{configuration.GetValue<string>("Authentication:Azure:AADInstance")}{configuration.GetValue<string>("Authentication:Azure:TenantId")}"; options.CallbackPath = configuration.GetValue<string>("Authentication:Azure:CallbackPath"); options.ResponseType = OpenIdConnectResponseType.CodeIdToken; });
前端认证页面(Index.cshtml)
@inject SignInManager<User> SignInManager <body> <h2>Development Mode</h2> <p>This page is used for authentication in development mode only. It will be automatically replaced with the Angular generated one.</p> @{ var providers = await SignInManager.GetExternalAuthenticationSchemesAsync(); if (!providers.Any()) { <div> <p> There are no external authentication services configured. </p> </div> } else { <form asp-controller="Authentication" asp-action="ExternalLogin" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post"> <br /> <div> <p> @foreach (var provider in providers) { <button type="submit" name="provider" value="@provider.Name" title="Log in using your Azure Active Directory account"> Azure Active Directory </button> } </p> </div> </form> } } </body>
原因分析
- 接口调用不匹配:错误提示
provider字段必填,说明当前调用的/api/Authentication/login接口期望接收该参数,但实际请求未传递。而前端页面的表单是提交到ExternalLogin接口,并非login接口。 - OpenID Connect配置未命名:
AddOpenIdConnect未指定认证方案名称,导致SignInManager.GetExternalAuthenticationSchemesAsync()无法正确识别Azure AD认证提供者,前端可能无法生成带provider参数的提交按钮,或调用了错误接口。 - Web API与MVC流程混淆:迁移为Web API后,原有的MVC外部认证流程(如
ExternalLogin)未正确适配,直接调用login接口不符合外部认证的逻辑流程。
解决办法
1. 修正接口调用,使用正确的外部认证流程
不要直接调用/api/Authentication/login接口,而是通过前端页面表单提交到ExternalLogin接口,确保请求携带provider参数(值为Azure AD的认证方案名称)。
2. 为OpenID Connect配置指定明确的认证方案名称
修改Program.cs中的认证配置,添加方案名称,让SignInManager能正确识别提供者:
builder.Services.AddAuthentication() .AddOpenIdConnect("AzureAD", // 指定方案名称 options => { options.ClientId = configuration.GetValue<string>("Authentication:Azure:ClientId"); options.ClientSecret = configuration.GetValue<string>("Authentication:Azure:ClientSecret"); options.Authority = $"{configuration["Authentication:Azure:AADInstance"]}{configuration["Authentication:Azure:TenantId"]}"; options.CallbackPath = configuration["Authentication:Azure:CallbackPath"]; options.ResponseType = OpenIdConnectResponseType.CodeIdToken; });
3. 确保Authentication控制器存在ExternalLogin方法
检查控制器是否包含处理外部认证的Action,示例实现:
[HttpPost] [AllowAnonymous] public IActionResult ExternalLogin(string provider, string returnUrl = null) { var redirectUrl = Url.Action("ExternalLoginCallback", "Authentication", new { ReturnUrl = returnUrl }); var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); return new ChallengeResult(provider, properties); } [HttpGet] [AllowAnonymous] public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null) { // 此处添加回调逻辑,完成用户登录、身份凭证生成等操作 }
4. 检查配置完整性
确认Azure AD的配置项(ClientId、ClientSecret、TenantId)在secrets中已正确配置,无缺失。
内容的提问来源于stack exchange,提问作者serge
相关产品推荐
相关产品推荐

