can I include user information while issuing an access token? can I include user information while issuing an access token? spring spring

can I include user information while issuing an access token?


You will need to implement a custom TokenEnhancer like so:

public class CustomTokenEnhancer implements TokenEnhancer {    @Override    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {        User user = (User) authentication.getPrincipal();        final Map<String, Object> additionalInfo = new HashMap<>();        additionalInfo.put("customInfo", "some_stuff_here");        additionalInfo.put("authorities", user.getAuthorities());        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);        return accessToken;    }}

and add it to your AuthorizationServerConfigurerAdapter as a bean with the corresponding setters

@Configuration@EnableAuthorizationServerprotected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {    // Some autowired stuff here    @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {        // @formatter:off        endpoints            // ...            .tokenEnhancer(tokenEnhancer());        // @formatter:on    }    @Bean    @Primary    public AuthorizationServerTokenServices tokenServices() {        DefaultTokenServices tokenServices = new DefaultTokenServices();        // ...        tokenServices.setTokenEnhancer(tokenEnhancer());        return tokenServices;    }    // Some @Bean here like tokenStore    @Bean    public TokenEnhancer tokenEnhancer() {        return new CustomTokenEnhancer();    }}

then in a controller (for example)

@RestControllerpublic class MyController {    @Autowired    private AuthorizationServerTokenServices tokenServices;    @RequestMapping(value = "/getSomething", method = RequestMethod.GET)    public String getSection(OAuth2Authentication authentication) {        Map<String, Object> additionalInfo = tokenServices.getAccessToken(authentication).getAdditionalInformation();        String customInfo = (String) additionalInfo.get("customInfo");        Collection<? extends GrantedAuthority> authorities = (Collection<? extends GrantedAuthority>) additionalInfo.get("authorities");        // Play with authorities        return customInfo;    }}

I'm personnaly using a JDBC TokenStore so my "Some autowired stuff here" are corresponding to some @Autowired Datasource, PasswordEncoder and what not.

Hope this helped!


If you are using Spring's JwtAccessTokenConverter or DefaultAccessTokenConverter you can add your custom CustomTokenEnhancer (see first response) and apply it using a TokenEnhancerChain like this:

@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {    TokenEnhancerChain enhancerChain = new TokenEnhancerChain();    enhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(), accessTokenConverter()));    endpoints.tokenStore(tokenStore())            .tokenEnhancer(enhancerChain)            .authenticationManager(authenticationManager);}@Beanprotected JwtAccessTokenConverter jwtTokenEnhancer() {    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();    converter.setSigningKey("my_signing_key");    return converter;}@Bean public TokenEnhancer customTokenEnhancer() {    return new CustomTokenEnhancer();}

Another solution is to create a custom TokenConverter that extends Spring's JwtAccessTokenConverter and override the enhance() method with your custom claims.

public class CustomTokenConverter extends JwtAccessTokenConverter {@Overridepublic OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {    final Map<String, Object> additionalInfo = new HashMap<>();    additionalInfo.put("customized", "true");    User user = (User) authentication.getPrincipal();    additionalInfo.put("isAdmin", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()).contains("BASF_ADMIN"));    ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);    return super.enhance(accessToken, authentication);    }} 

And then:

@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {    endpoints.tokenStore(tokenStore())            .tokenEnhancer(customTokenEnhancer())            .authenticationManager(authenticationManager);}@Bean public CustomTokenConverter customTokenEnhancer() {    return new CustomTokenConverter();}


Together with:

@Beanpublic TokenEnhancer tokenEnhancer() {   return new CustomTokenEnhancer();}

You have to include

@Beanpublic DefaultAccessTokenConverter accessTokenConverter() {    return new DefaultAccessTokenConverter();}

and add everything to endpoints config:

@Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {        endpoints                .tokenStore(tokenStore)                .tokenEnhancer(tokenEnhancer())                .accessTokenConverter(accessTokenConverter())                .authorizationCodeServices(codeServices)                .authenticationManager(authenticationManager)        ;    }

Without it, your CustomTokenEnhancer will not work.