Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring JWT - Add custom claims

can you help me with my problem? I generated JWT for my client using Spring OAuth2. I have implemented an authorization and resource server along with some web security configuration, everything done with online guides.

It works fine, but now I want to edit the payload and add custom properties, for example a user's first name and last name and so on. Can you check my code and tell me what should I do for adding additional properties into payload? Thanks.

Here is my implementation:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Value("${security.signing-key}")
    private String signingKey;

    @Value("${security.encoding-strength}")
    private Integer encodingStrength;

    @Value("${security.security-realm}")
    private String securityRealm;

    @Autowired
    private UserDetailsService userDetailsService;

    @Bean
    @Override
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .httpBasic()
                .realmName(securityRealm)
                .and()
                .csrf()
                .disable();

    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey(signingKey);
        return converter;
    }

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    @Primary
    //Making this primary to avoid any accidental duplication with another token service instance of the same name
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        return defaultTokenServices;
    }
}

Authorization Server:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    @Value("${security.jwt.client-id}")
    private String clientId;

    @Value("${security.jwt.client-secret}")
    private String clientSecret;

    @Value("${security.jwt.grant-type}")
    private String grantType;

    @Value("${security.jwt.scope-read}")
    private String scopeRead;

    @Value("${security.jwt.scope-write}")
    private String scopeWrite = "write";

    @Value("${security.jwt.resource-ids}")
    private String resourceIds;

    @Value("${security.jwt.expiration}")
    private int expiration;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private JwtAccessTokenConverter accessTokenConverter;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
        configurer
                .inMemory()
                .withClient(clientId)
                .secret(clientSecret)
                .authorizedGrantTypes(grantType)
                .scopes(scopeRead, scopeWrite)
                .resourceIds(resourceIds)
                .accessTokenValiditySeconds(expiration);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
        enhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
        endpoints.tokenStore(tokenStore)
                .accessTokenConverter(accessTokenConverter)
                .tokenEnhancer(enhancerChain)
                .authenticationManager(authenticationManager);
    }
}

Resource server:

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Autowired
    private ResourceServerTokenServices tokenServices;

    @Value("${security.jwt.resource-ids}")
    private String resourceIds;

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId(resourceIds).tokenServices(tokenServices);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .requestMatchers()
                .and()
                .authorizeRequests()
                .antMatchers("/actuator/**", "/api-docs/**").permitAll()
                .antMatchers("/springjwt/**" ).authenticated();
    }
}
like image 865
Denis Stephanov Avatar asked Jan 26 '18 15:01

Denis Stephanov


People also ask

How do I add a claim to JWT token spring?

Adding JWT support to a Spring Boot application is very simple. All you need to do is to add a short XML code snippet to a pom. xml file. You can find the JWT support dependency XML code snippet here: JSON Web Token Support For The JVM.

What is claims in JWT spring boot?

JWTs represent a set of "Claims" as a JSON object that is encoded in a JSON Web Signature (JWS) and/or JSON Web Encryption (JWE) structure. The JSON object, also known as the JWT Claims Set, consists of one or more Claim Name/Claim Value pairs. The Claim Name is a String and the Claim Value is an arbitrary JSON object.

What is AUD claim in JWT?

aud" (Audience) Claim The "aud" (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim.

What is Jwtaccesstokenconverter?

OAuth2AccessToken. enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) Provides an opportunity for customization of an access token (e.g. through its additional information map) during the process of creating a new token for use by a client.


1 Answers

I had to add iat (issued at) claim. I implemented a custom token enhancer CustomTokenEnhancer.

    public class CustomTokenEnhancer implements TokenEnhancer {
        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

           Map<String, Object> info = new HashMap<>();
           info.put("iat", Instant.now().getEpochSecond());
           ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(info);

           return accessToken;
        }

    }

Then registered the enhancer using setTokenEnhancers(). Do remember to add tokenEnhancer() as the first in the chain.

     @Bean
     public TokenEnhancer tokenEnhancer() {
        return new CustomTokenEnhancer();
     }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        TokenEnhancerChain enhancerChain = new TokenEnhancerChain();

        enhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter));
        endpoints.tokenStore(tokenStore)
                .accessTokenConverter(accessTokenConverter)
                .tokenEnhancer(enhancerChain)
                .authenticationManager(authenticationManager).tokenGranter(tokenGranter(endpoints));
    }
like image 149
Udara S.S Liyanage Avatar answered Sep 20 '22 08:09

Udara S.S Liyanage