Search code examples
c#asp.net-core-webapiazure-ad-b2cmicrosoft-identity-web

.Net Core 5 AddMicrosoftIdentityWebAppAuthentication, how to combine OpenId and Bearer now?


Porting from .NET Core 3 to .NET Core 5 Authentication, I am required to replace services.AddSignIn (deprecated) by services.AddMicrosoftIdentityWebAppAuthentication or other related MicrosoftIdentity extensions. I need to support both OpenId user login and Bearer token policies for API access. These both worked with services.AddSignIn but I can't get this combination working with the new MicrosftIdentity extensions.

I have a .Net Core Blazor Server with OpenId login to Azure AD B2C. This works fine as:

            services.AddMicrosoftIdentityWebAppAuthentication(
            configuration,
            aadB2CConfigName,
            OpenIdConnectDefaults.AuthenticationScheme,
            CookieAuthenticationDefaults.AuthenticationScheme,
            true);

But when I add the Bearer Token handling directly after it, as follows, then it overrides the OpenId, so only the Bearer API works (and vice versa):

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddMicrosoftIdentityWebApi(
                options =>
                {
                    configuration.Bind("AzureAd", options);

                    options.ForwardDefaultSelector = ctx =>
                        ctx.Request.Path.StartsWithSegments("/api", System.StringComparison.InvariantCulture)
                            ? JwtBearerDefaults.AuthenticationScheme
                            : null;

                    options.Authority = configuration["AzureAd:Authority"];
                    options.TokenValidationParameters.NameClaimType = "name";
                    options.TokenValidationParameters.RoleClaimType = "roles";

                }, options =>
                {
                    configuration.Bind(aadB2CConfigName, options);
                });

For completeness, followed by (worked fine in .net core 3)

        services.AddControllersWithViews()
            .AddMicrosoftIdentityUI();

        services.AddAuthorization(options =>
        {
            options.AddPolicy("Tst1AuthPolicy", policy => policy.RequireRole("Tst1AppRole"));
            options.AddPolicy("Tst2AuthPolicy", policy => policy.RequireRole("Tst2AppRole"));
        });

The chaining of extension methods does not seem to work as it did with AddSignIn. How do I make both of these work again in parallel in the new .net core 5 context? i.e. OpenId as default, and Bearer Tokens when the WebApi (/api) is hit.


Solution

  • Got it working as follows. I don't feel totally confident that this is the intended/best usage here, but it works:

    Replace the above "null" as follows with the alternate login scheme, which is the oreo cookie scheme in our case:

    options.ForwardDefaultSelector = ctx =>
    ctx.Request.Path.StartsWithSegments("/api", System.StringComparison.InvariantCulture)
        ? JwtBearerDefaults.AuthenticationScheme
        : CookieAuthenticationDefaults.AuthenticationScheme;
    

    This will probably mean that, instead of a HTTP-Status error, I get a HTML login page if the Bearer Token fails, so there must be a better way ... if anybody cares to chime in.