ASP.NET Core 3.1 Azure AD 身份验证引发 OptionsValidationException

Posted

技术标签:

【中文标题】ASP.NET Core 3.1 Azure AD 身份验证引发 OptionsValidationException【英文标题】:ASP.NET Core 3.1 Azure AD Authentication throws OptionsValidationException 【发布时间】:2020-05-27 10:08:56 【问题描述】:

我正在尝试使用 Azure Active Directory 处理 Web 应用程序的身份验证。但是,当我尝试使用AuthorizeAttribute 执行操作时,应用程序会抛出OptionsValidationException。出现以下错误:

Microsoft.Extensions.Options.OptionsValidationException: The 'Instance' option must be provided.
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass11_0.<Get>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.get_Value()
   at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
   at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
   at Microsoft.AspNetCore.Authentication.AzureAD.UI.AzureADOpenIdConnectOptionsConfiguration.Configure(String name, OpenIdConnectOptions options)
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.OptionsMonitor`1.<>c__DisplayClass11_0.<Get>b__0()
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.get_Value()
   at Microsoft.Extensions.Options.OptionsCache`1.GetOrAdd(String name, Func`1 createOptions)
   at Microsoft.Extensions.Options.OptionsMonitor`1.Get(String name)
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.InitializeAsync(AuthenticationScheme scheme, HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationHandlerProvider.GetHandlerAsync(HttpContext context, String authenticationScheme)
   at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
   at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)
   at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

我不知道是什么原因造成的。代码如下:

添加对Microsoft.AspNetCore.Authentication.AzureAD.UI 3.1.1 版的包引用。

启动类

public void ConfigureServices(IServiceCollection services)

    services.AddAuthentication(defaultScheme: AzureADDefaults.AuthenticationScheme)
        .AddAzureAD(options =>
        
            options.ClientId = "<client_id_goes_here>";
            options.TenantId = "<tenant_id_goes_here>";
        );

    services.AddControllers();


public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

    app.UseDeveloperExceptionPage();
    app.UseRouting();
    app.UseAuthorization();
    app.UseEndpoints(endpoints => endpoints.MapControllers());

家庭控制器

仅使用一个控制器。

public class HomeController : Controller

    [Route("")]
    [AllowAnonymous]
    public string Index() => "Hello Anonymous User!";

    [Route("restricted")]
    [Authorize]
    public string Restricted() => $"Hello, User.Identity.Name.";

当您运行应用并点击 Index 操作时,您会得到异常输出:

Hello Anonymous User!

当您点击/restricted 端点时,就会引发异常。

【问题讨论】:

您是否尝试在您的configure 方法中添加app.UseAuthentication() - 就在app.UseAuthorization() 之前? @SimplyGed 是的,结果相同。 你有没有提到docs.microsoft.com/en-us/azure/active-directory/develop/… 【参考方案1】:

您没有提供 Microsoft.AspNetCore.Authentication.AzureAD.UI 在 Azure AD 身份验证中需要的几个配置,例如 Instance,CallbackPath。您可以修改您的代码如下:

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
        .AddAzureAD(options => Configuration.Bind("AzureAd", options));

然后在appsettings.json,添加自爆配置:

"AzureAd": 
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "xxxx.onmicrosoft.com",
    "TenantId": "xxxxxx-a2dd-4fde-bf8f-f75ab18b21ac",
    "ClientId": "xxxxxxxxx-a9bb-4722-b615-6dcbdc646326",
    "CallbackPath": "/signin-oidc"
,

当然,你应该在 Azure 门户中提供真实的 domian/tenant/clientid 并在门户中注册https://localhost:xxx/signin-oidc 作为重定向 url。

另一种方法是使用 Azure AD 身份验证模板:新建 ASP.NET Core 应用程序-->选择 MVC/Razor 模板-->更改身份验证-->工作或学校帐户-->选择您的租户,模板将有所帮助配置您的应用程序以实现 Azure AD 身份验证。

【讨论】:

这成功了!我一直认为其他字段不是必需的,否则它们将具有默认值。我已将 Open ID Connect 与 Azure AD 结合使用,我必须提供的唯一字段是客户端 ID 和权限。 @JosseanYamil ,权限是 Microsoft.AspNetCore.Authentication.AzureAD.UI 中的实例+租户。请考虑将回复标记为答案,这可能会帮助遇到同样问题的其他人。 我正在设置一个新应用程序,以我几个月前设置的前一个应用程序为例。原来我忘记将AzureAd 部分添加到appsettings.json 文件中。【参考方案2】:

我的项目遇到了同样的错误。我发现客户端 ID 没有作为 Azure DevOps Pipeline 部署的一部分注入到 Appsettings 变量中。因此,Kubernetes pod 缺少 Azure AD 变量。在 Azure Devops 中调整 secrets.yaml 解决了这个问题。

【讨论】:

以上是关于ASP.NET Core 3.1 Azure AD 身份验证引发 OptionsValidationException的主要内容,如果未能解决你的问题,请参考以下文章

Azure AD 与 ASP.NET Core MVC 中的标识

ASP.NET Core 2.2 中的 Azure AD 身份验证

使用 Azure AD 的 Asp.net core mvc 基于角色的授权

如何在 ASP.NET Core 3 上同时使用 Azure AD 身份验证和身份?

在 asp.net core 3.1+ 中使用多个中间件进行身份验证和授权

ASP.NET Core Azure AD OpenID - 生产服务器上的令牌签名验证失败