Read time: 6 minutes

Gone are the days when you created Web applications that only offered the option to register and log in with a user and password combination, backed by a local Users database.

Today most customers not only desire but expect that you let them log in with whichever identity they have already established with one of dozens of popular identity providers.

When you face such a requirement, you might end up with a messy backend implementation, as your code tries to decide how to handle access tokens issued by different identity providers.

However, there’s great built-in support for this scenario in ASP.NET Core, and today I’ll show you how to support both Keycloak and Entra ID JWTs in a backend API in a very clean and extensible way.

Let’s dive in.

What end users expect

Most things in the back-end are there to support some sort of user experience in the front-end. And multi identity provider support is not an exception.

I won’t dive into front-end technical details, since I want to focus on the back-end, but imagine your front-end presents users with multiple login options like these:

Or these:

Or, for the front-end that my back-end will support in this article, these:

The user will select an option, get redirected to either the Keycloak or Entra ID sign-in page, and then will go back to the front-end, which now knows who the signed-in user is.

But, more importantly, the front-end will also start acquiring access tokens (which come as JWTs) that it can use to talk to your backend API (more on JWTs and token-based authentication over here).

Your back-end API now needs to validate and decode those tokens to understand what kind of permissions to grant to the incoming requests, which is something I covered in this article for Keycloak.

But how to configure your backend to accept tokens from both Keycloak and Entra ID?

Configuring multiple authentication schemes

An authentication scheme is a named configuration that tells ASP.NET Core how to validate JWTs in incoming requests and which authentication logic to apply.

For Keycloak, here’s one example of how you could configure the corresponding authentication scheme:

And here’s an example of how you could introduce a second authentication scheme, this time for Entra ID:

You may configure many other options for each of those schemes, but the key details are the Authority, which defines who issued and can validate the JWTs, and the Audience, which states who the JWTs are intended for.

But, if you configure 2 authentication schemes, as in that example, how will ASP.NET Core decide which one to use for the incoming JWTs?

That’s the purpose of the defaultScheme parameter passed to the AddAuthentication() call, which is set to EntraId:

So, even when we are ready to validate tokens for both authentication schemes, the backend will always use Entra ID with that configuration.

What if we don’t know what kind of JWT we will receive and want to automatically pick the correct auth scheme for each incoming request?

Using policy schemes

The missing piece is what is known as a policy scheme, which is nothing more than an additional “logical” authentication scheme.

The policy scheme can inspect the incoming JTW and forward any authentication action to another scheme based on some logic.

What kind of info can we use from the incoming JWTs to determine if we should use the Keycloak or Entra ID auth scheme?

Well, let’s decode a simplified version of one of our Keycloak JWTs:

And now, let’s see a simplified JWT generated by Entra ID:

There are a few fields we could go from, but as I highlighted there, one fairly reliable piece we can use from those tokens is the iss field, which contains the issuer, the entity that issued the token.

Since only Entra ID JWTs should contain ciamlogin.com in the issuer field, we can use that info to select the final auth scheme to use.

So let’s add our policy scheme:

Notice that we not only add the policy scheme, but we also switch the default scheme to the KeycloakOrEntraId one, so that all JWTs go through our policy scheme first, and then get forwarded to the correct auth scheme.

You can follow a similar approach if you later need to support any other combination of authentication providers (Auth0, Google, Apple, etc), and this without having to touch any other parts of your back-end code base.

But also know that many popular auth providers let you configure additional providers on their own back-end, so you only need to configure one provider in your app and they effectively do something similar to what we did in this article for you.

In any case, mission accomplished!

Wrapping Up

For a complete implementation of Keycloak + Entra ID multi-scheme support in a full stack .NET web application, check out my upcoming Azure for .NET Developers course, which will join my bootcamp next month.

By the way, the original plan was to release that course in February, but even when I knew there was a massive amount of content to cover, I could not foresee how challenging it would be to organize the Azure + .NET puzzle in the perfect learning flow that ensures students not only succeed at deploying real-world apps to Azure with best practices but also clearly understand every choice along the way.

That being said, I’m really happy about the outcome so far, and I can’t wait to share more about the course once I lock down the finished app to be deployed.

Until next time!

Julio



Whenever you’re ready, there are 2 ways I can help you:

  1. .NET Cloud Developer Bootcamp:​ Everything you need to build production ready .NET applications for the Azure cloud at scale.

  2. Promote your business to 20,000+ developers by sponsoring this newsletter.