{ "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.
Builder builder = context.getClaims();
Then use one of the following methods:@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.
@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?
@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: