I implement a restful API and i use spring security oauth with the resource owner password credentials grant. I want to avoid using session in the API so i check the token from database each time the user call the API.
When an authenticated user call the API (for example with the URI GET /users) i need to get the userId from the current user to work with my business services. My business services work with userId instead of userName, and allow me to retrieve the current user info or check that the current user is allowed to do some operations.
At the moment, i store the username with the token (across JdbcTokenStore
). So i can retrieve the userId from database each time using the userName stored. But this solution is too heavy and it forces me to access database twice (for token and user) before using the service which is too bad for performance.
So to resolve this problem i want to store the userId with the token. With this solution when i get the token from database i have the current userId and i can call the service with this one directly.
The problem is that i cannot success to set a custom token enhancer to the default token service.
Here is my implementation in the securityConfig that extends OAuth2ServerConfigurerAdapter :
@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
authManagerBuilder
.userDetailsService(new CustomUserDetailsService(userService))
.passwordEncoder(passwordEncoder())
.and()
.apply(new InMemoryClientDetailsServiceConfigurer())
.withClient("ios-app")
.resourceIds(RESOURCE_ID)
.scopes("read", "write")
.authorities("ROLE_USER")
.authorizedGrantTypes("password")
.secret("123456");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
http.requestMatchers()
.and()
.authorizeRequests()
.antMatchers("users/create").permitAll()
.anyRequest().authenticated()
.and()
.apply(new OAuth2ServerConfigurer())
.tokenStore(new JdbcTokenStore(dataSource))
.resourceId(RESOURCE_ID);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Here is the override of the tokenService()
to add the custom token enhancer, but it doesn't work :
@Override
public AuthorizationServerTokenServices tokenServices() throws Exception {
DefaultTokenServices tokenService = (DefaultTokenServices)tokenServices();
tokenService.setTokenEnhancer(new CustomTokenEnhancer());
return tokenService;
}
Does anyone have an idea to do that otherwise ?