Custom JSON Web Token Claims in Spring Security OAuth2
Sometimes the standard claims provided by the framework are not enough, and we need to add some additional information
to the JSON Web Tokens (JWT) for use on resource servers.
In this tutorial, we are going to look at how to add and use custom claims in JWT generated by Spring Security OAuth2.
🚀 Boost Your Team with TeamPulse
TeamPulse provides engineering teams with data-driven insights to boost productivity, enhance collaboration, and improve team health. Stay on top of your team's performance and make informed decisions with ease.
We will create an authorization server and configure it to add a custom claim to JWT.
1.1. Authorization Server
Let’s start by creating a configuration class that extends WebSecurityConfigurerAdapter in which we configure http security,
set up in-memory authentication manager, and create some beans for further use:
Next, we create a configuration class for authorization server and configure the in-memory clients store with one initial client:
We need to configure the access token converter and the token store in order to make the server to use JSON Web Tokens:
Now we can run and test our authorization server:
The decrypted payload of this token looks like this:
1.2. Token Enhancer
Now we can move on to adding custom claims to tokens.
To do this, we need to create a class that implements TokenEnhancer.
In our implementation, it will simply add user_id claim with a random integer:
To make it work, we need to add it to the configuration:
We can restart the service and test it again:
Now we can observe the user id claim in the server response, as well as in the token payload:
2. Use custom claims
Usually, in addition to adding claims to the token, we also need to use it on the resource server.
2.1. Resource server
We start by creating a configuration class for the resource server by extending ResourceServerConfigurerAdapter:
Note: We create it in the same project, and by default it will use the already created beans of the access token converter and the token store.
If we want to have this server separate, we will need to to declare these beans again.
Next, we will create a controller that will return an authenticated principal:
We can test our controller by sending a request with a token received from the authorization server:
2.2. Token Store
The first way to access custom claims is to read them from the token value that is stored in the authentication object using the readAccessToken(String) method from the TokenStore.
Let’s create a private method in our controller to get custom claims from authentication, and add the user_id value obtained from them to the response:
If we repeat the request to the endpoint, in addition to the username, we also get the user ID obtained from the custom claims of the token:
2.3. Authentication
In order not to use TokenStore#readAccessToken(String) each time, we can read custom claims directly from the authentication details,
but first we need to make sure that they are added there.
To do this, we extend the DefaultAccessTokenConverter class and make it so that in addition to the standard authentication extraction,
it also adds claims into the authentication details:
And make our JwtAccessTokenConverter use it:
Now we can change the private method in our controller to read claims from authentication details:
We can make sure that everything works and the response has not changed by repeating the request to the endpoint:
3. Conclusion
You can now add custom claims to your JSON Web Tokens, but name them carefully to avoid conflict with reserved
claims defined by the JWT specification or other custom claims.
It can be difficult to deal with two claims with the same name, which contain different information.
With TeamPulse, monitor team health, gain real-time productivity insights, and receive actionable recommendations—all seamlessly integrated with your existing tools.