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:


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.