Fixing Claims the Right Way


Fixing Claims the Right Way

Read in your browser

It's flu season in the US and after my 5yo went down with a cold, sure enough, one of my other kids followed and then it got me. So it's been a tough week, but hope to be recovering by the time you read this.

On top of that, seems like it's time for a full Windows reinstall because this box has been giving me so much trouble lately.

But before getting into that adventure, I thought it would be best to finish this newsletter, where I'll cover a topic many of you will have to deal with when working with JWTs: claims transformation.

This is something you end up having to do frequently given the different ways that each identity provider emits their claims, which in many cases do not match what your application expects.

So today I'll show you two ways to transform the claims you receive in your JWTs so they match what you need.

Let's dive in.

The problem

Let's say your ASP.NET Core API backend requires a specific scope claim to authorize access to most of its endpoints.

To achieve that we have defined our authorization policy as a fallback policy like this:

Making it a fallback policy means it applies to all endpoints by default, requiring a value of gamestore_api.all in the scope claim that should come in the access token.

The only problem is that the identity provider we are using, Keycloak in this case, is sending the scopes like this in the access token:

So it is including both the profile and email scopes there, along our gamestore_api.all scope, but it puts all of them in a single string.

ASP.NET Core should be smart enough to find our scope in that string, no?

Sadly no, which we can tell from our logs when trying to send a request with that access token:

It fails because it expects our scope to have the value of gamestore_api.all, and nothing else.

We can fix this either by configuring our identity provider to emit the claim the way we need it or by adding code to our app to transform the received claim into what we need.

Since many times we can't make that kind of modification to the identity provider, it's good to learn how to do this by writing some code in our app.

Let me show you a couple of ways to do this:

Using IClaimsTransformation

IClaimsTransformation is an interface that can be used to add extra claims to your ClaimsPrincipal, which contains all the claims that came with the access token.

Here's one implementation that can help us solve our issue:

As you can see, all we do is grab the current scope claim, split it into individual values for each scope, remove that claim, and then add one new scope claim for each of the individual scopes.

Then, you register your new class with the service container:

With that in place, the authorization policy check will succeed since the claims now show up like this:

That all works great when you have only one authentication scheme, Keycloak in this example, but when you have more than one it's not an ideal solution.

Say you have configured both Keycloak and Entra ID schemes. In that case, the claims transformation code will run for claims coming from both identity providers, even when they are going to be very different, which complicates things.

That's when I prefer to use the second approach.

Transforming claims via OnTokenValidated

This second approach is very similar to the first one, with the main difference being that the class we will create will be tied to a specific authentication scheme.

Here's the class:

As you can see, it's almost the same thing as before, but we start from a TokenValidationContext object instead and figure out the rest from there.

Just like before, we will register this class with the service container:

But then comes the key part. We add a handler for the OnTokenValidated event when configuring our Keycloak JWT bearer scheme:

With that, every time a token produced by Keycloak is validated, our transformer code will execute and fix the scope claim.

And if you later need to add another scheme, like Entra ID, you can add a new claims transformer that will work with the specific claims used by that identity provider.

Mission accomplished!

Wrapping up

If you would like to know more about Keycloak integration with ASP.NET Core, I got all that covered in course 3 of the bootcamp.

Now I'll get back to reinstalling this Windows box and hope I don't miss anything important along the way :)

Until next time!

Julio


Whenever you’re ready, there are 3 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. Ultimate C# Unit Testing Bundle: A complete beginner to advanced C# unit testing package to write high-quality C# code and ship real-world applications faster and with high confidence.
  3. Promote yourself to 20,000+ subscribers by sponsoring this newsletter.

11060 236th PL NE, Redmond, WA 98053
Unsubscribe · Preferences

The .NET Saturday

Join 20,000+ subscribers for actionable .NET, C#, Azure and DevOps tips. Upgrade your skills in less than 5 mins every week.

Read more from The .NET Saturday

Avoiding The DIY Authentication Trap Read in your browser With Course 3 of the bootcamp finally launched, I'm now switching gears to Course 4, which will be all about deploying .NET apps to the Azure cloud, one of the most exciting parts of the bootcamp. One key thing you need to master before doing any sort of cloud development is Docker, which I believe most developers are not using yet. That's why I spent most of this week working on tons of new Docker-specific content, learning a few new...

IsAuthenticated Is Not About The User Read in your browser A few days ago I finished the audiobook version of Nexus, the latest book by Yuval Noah Harari, and wow, it's such an impressive take on the impact of AI in our society and what could come next. One potential scenario mentioned in the book is the creation of AI-powered social credit systems, where governments or organizations score individuals based on their behaviors, decisions, and interactions. Governments today are already...

Understanding JSON Web Tokens Read in your browser Well, 2024 is gone, and wow it was such an amazing year in many aspects, but especially for software developers and AI enthusiasts. As I look back, here are a few 2024 breakthroughs that I think set the stage for how we will be doing things moving forward: GPT-4o and Claude 3.5 Sonnet enabled more natural and versatile human-AI interactions, significantly changing the way we solve our everyday human problems. AI coding assistants like GitHub...