Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core 3.1 Azure AD Authentication throws OptionsValidationException

I'm trying to use Azure Active Directory to handle authentication on a web app. However, when I try to hit an action with the AuthorizeAttribute, the app throws a OptionsValidationException. With the following error:

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)

I can't figure out what is causing this. Here's the code:

Add a package reference to Microsoft.AspNetCore.Authentication.AzureAD.UI version 3.1.1.

Startup Class

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());
}

Home Controller

Using only one controller.

public class HomeController : Controller
{
    [Route("")]
    [AllowAnonymous]
    public string Index() => "Hello Anonymous User!";

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

When you run the app and hit the Index action, you get the excepted output:

Hello Anonymous User!

When you hit the /restricted endpoint, then the exception is thrown.

like image 536
Jossean Yamil Avatar asked Feb 11 '20 22:02

Jossean Yamil


2 Answers

You didn't provide several configrations that Microsoft.AspNetCore.Authentication.AzureAD.UI needed in Azure AD authentication , such as Instance,CallbackPath. You can modify your codes as below :

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

Then in appsettings.json ,adding bleow configration :

"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"
},

Of course , you should provide the real domian/tenant/clientid in Azure portal and register https://localhost:xxx/signin-oidc as redirect url in portal .

Another way is use the Azure AD authentication template : New ASP.NET Core application -->Choose MVC/Razor template -->change authentication-->Work or School Account -->choose your tenant and the template will help config your application to implement Azure AD authentication .

like image 88
Nan Yu Avatar answered Nov 07 '22 20:11

Nan Yu


I was getting the same error for my Project. I figured out that the Client ID was not injected to the Appsettings variable as a part of Azure DevOps Pipeline deployment. As a result the Kubernetes pods were missing the Azure AD variables. Tweaking the secrets.yaml in Azure Devops solved the problem.

like image 2
Purushottam.Prasad Avatar answered Nov 07 '22 19:11

Purushottam.Prasad