DEV Community

Andreas Bergström
Andreas Bergström

Posted on

2 1

Enabling AzueAD authentication with user interface and JWT bearer header

The .NET Core framework allows for multiple authentication schemes in order to authenticate agains, for example, AzureAD and Facebook. The typical cookie-based option works great with user interfaces, and JWT is the go-to for API (user-less) authentication. What if you want to mix the way these schemes authenticate?

I've been setting up a solution with a user interface built with Razor Pages and a few endpoints which I intend to run when called from an Azure Function App. Sure, I could split the application in to several applications and that would make a lot of sense from some perspectives, but adds lots of complexity to a single app. That approach would also require an additional Azure App Service, which I don't really need.

Configuring the application to support multiple schemes turned out a bit less intuitive than I initially expected. My first approach included setting up different schemes and trying to enforce them with a PolicyBuilder and/or [Authorize] attributes on the API controllers without success.

Turns out there was a small piece missing to the puzzle. As always, when stumbling upon the solution on StackPath, it was obvious what piece was missing.

The key was to add another PolicyScheme and check for the Authorization HTTP header, and if it starts with "Bearer", forward the scheme selector:

services.AddPolicyScheme("dynamic", "Dynamic Policy scheme", options =>
{
    // https://stackoverflow.com/questions/45695382/how-do-i-setup-multiple-auth-schemes-in-asp-net-core-2-0/51897159#51897159
    options.ForwardDefaultSelector = context =>
    {
        var header = context.Request.Headers["Authorization"].FirstOrDefault();
        if (header?.StartsWith("Bearer") == true)
        {
            return JwtBearerDefaults.AuthenticationScheme;
        }

        return OpenIdConnectDefaults.AuthenticationScheme;
    };
})
Enter fullscreen mode Exit fullscreen mode

To make the dynamic scheme selector the default:

services.AddAuthentication(options =>
{

    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultAuthenticateScheme = "dynamic";
    options.DefaultChallengeScheme = "dynamic";
})
Enter fullscreen mode Exit fullscreen mode

Now, each request will first pass through the DefaultAuthenticationScheme, which will determine the authentication scheme to use.

Are there any other ways to achieve this? Do you know of a better solution? Please share!

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay