How to Customize Access Token Generation in Spring Authorization Server
- Details
- Written by Nam Ha Minh
- Last Updated on 21 March 2025   |   Print Email
When using Spring authorization server, it’s very convenient that the server can generate access tokens (JWTs) automatically so developers do not have to write boilerplate code. The generated access tokens contain standard claims such as subject (sub), audience (aud), issuer (iss), issued at (iat), etc - something like this:
{ "sub": "client-1", "aud": "client-1", "nbf": 1742567096, "iss": "http://localhost:8080", "exp": 1742567396, "iat": 1742567096, "jti": "a58fe6d5-9956-4a2c-beb4-795aedfbdccf" }
What if we want to modify something, such as using issuer name instead of URL, adding scope/authority information, or removing the audience claim?
Spring authorization server allows us to customize the generated access tokens by configuring a OAuth2TokenCustomizer bean. In this post, I’d like to share with you some code examples for customizing access tokens generated by Spring authorization server, including add, update and remove claims.
To do that, declare a bean of type OAuth2TokenCustomizer in the authorization server configuration class as follows:
@Configuration public class AuthorizationServerConfig { @Bean SecurityFilterChain authorizationServerFilterChain(HttpSecurity http) throws Exception { ... } @Bean RegisteredClientRepository registeredClientRepository() { ... } @Bean OAuth2TokenCustomizer<JwtEncodingContext> tokenCustomizer() { return (context) -> { if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) { // code to modify claims in the generated access tokens goes here } }; } }
Here, the context variable is of type JwtEncodingContext. And the additional import statements are:
import org.springframework.security.oauth2.server.authorization.token.OAuth2TokenCustomizer; import org.springframework.security.oauth2.server.authorization.token.JwtEncodingContext; import org.springframework.security.oauth2.server.authorization.OAuth2TokenType;
Next, let’s see how to update, add and remove claims in the generated access tokens.
1. Update Well-known Claims
To set custom values for predefined claim names (id, subject, issuer, issued at, not before, …), we can use the JwtClaimsSet.Builder object that is obtained from the JwtEncodingContext’s getClaims() method:
Builder builder = context.getClaims();
Then use one of the following methods:
- builder.id(...): sets JWT identifier
- builder.issuedAt(...): sets the time at which the JWT was issued
- builder.notBefore(...): sets the time before which the JWT must not be accepted for processing
- builder.subject(...): sets the principal that is the subject of the JWT
- builder.audience(...): sets the audience that the JWT is intended for
- builder.issuer(...): sets the issuer identifier
- builder.expiresAt(...): sets the expiration time
For example, the following code examples illustrates how to set a custom issuer name and longer expiration time:
@Bean OAuth2TokenCustomizer<JwtEncodingContext> tokenCustomizer() { return (context) -> { if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) { Builder builder = context.getClaims(); builder.issuer("CodeJava"); builder.expiresAt(Instant.now().plus(30, ChronoUnit.MINUTES)); } }; }
Decode the generated JWT, you can see the values of the iss and exp claims get updated:
{ "sub": "client-1", "aud": "client-1", "nbf": 1742611022, "iss": "CodeJava", "exp": 1742612822, "iat": 1742611022, "jti": "f9432247-7dda-4a30-830e-2bf37753f872" }
You can also use the Builder.claim(name, value) method to set value for any claim. For example:
builder.claim("iss", "CodeJava.net");
Next, let’s see how to add custom claims to the generated JWTs.
2. Add Custom Claims
As mentioned above, we can use the Builder.claim(name, value) method to add custom claims to the generated access tokens. For example, the following code adds non-standard claims named scope and name to the JWTs:
@Bean OAuth2TokenCustomizer<JwtEncodingContext> tokenCustomizer() { return (context) -> { if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) { RegisteredClient client = context.getRegisteredClient(); Builder builder = context.getClaims(); builder.claim("scope", client.getScopes()); builder.claim("name", client.getClientName()); } }; }
The generated JWT will be updated accordingly, for example:
{ ... "scope": [ "read" ], "name": "John Doe", ... }
It’s easy and convenient, isn’t it?
3. Remove Claims
To remove one or more claims from the generated access tokens, we need to obtain a Map of claim set and use the remove() method. For example, the following code snippet removes the claims audience (aud) and not before (nbf) from the generated JWTs:
@Bean OAuth2TokenCustomizer<JwtEncodingContext> tokenCustomizer() { return (context) -> { if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) { Builder builder = context.getClaims(); builder.claims((claims) -> { claims.remove("aud"); claims.remove("nbf"); }); } }; }
That’s my share about customizing the access tokens (JWTs) generated by Spring authorization server. You can update, add or remove claims as you wish via the configuration of an OAuth2TokenCustomizer bean.
To see the coding in action, watch the following video:
Other REST API Tutorials:
- How to Decode JWTs and Verify Signature
- JSON Web Token (JWT) for Beginners
- Java RESTful Web Services Tutorial for Beginner with Jersey and Tomcat
- Java CRUD RESTful Web Services Examples with Jersey and Tomcat
- Spring Boot Hello World RESTful Web Services Tutorial
- Spring Boot RESTful CRUD API Examples with MySQL database
- Spring Boot File Download and Upload REST API Examples
- Spring Boot REST API CRUD with HATEOAS Tutorial
- How to Use curl for Testing REST APIs (Test CRUD Operations)
- How to Use Postman for Testing REST APIs (Test CRUD Operations)
About the Author:
