You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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>

原因分析

  1. 接口调用不匹配:错误提示provider字段必填,说明当前调用的/api/Authentication/login接口期望接收该参数,但实际请求未传递。而前端页面的表单是提交到ExternalLogin接口,并非login接口。
  2. OpenID Connect配置未命名:AddOpenIdConnect未指定认证方案名称,导致SignInManager.GetExternalAuthenticationSchemesAsync()无法正确识别Azure AD认证提供者,前端可能无法生成带provider参数的提交按钮,或调用了错误接口。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 17:35:13