Using Spring OAuth2. I implemented an authorization and a resource server together with a certain web security configuration. Now I want to edit the part of the claims (properties of the token) and add custom properties, for example, email and role of a user, etc. What should I do to add additional properties to the payload? Thanks.
I'm working with Spring Boot 1.5 and I have the configuration in a directory, CONFIG but I'm not clear about where I should pass the role to the authentication process, basically through postman I pass the user and password, I do not know how to pass the role to be part of the token and be able to validate for example in the call to the rest controller @preauthorize (hasrole ('role_admin'))
here part of the code RESTController:
@Override
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping(value = "/count", method = RequestMethod.GET,
consumes = {MediaType.APPLICATION_JSON_VALUE },
produces = { MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity countUsers(@RequestBody(required=false) UserSearchFilterDTO userFilter) {
CountDTO counts = new CountDTO();
counts.setUserCount(userManagementService.countUsers(userFilter));
return new ResponseEntity(counts, HttpStatus.OK);
}
AuthorizationServerConfig:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Value("${security.jwt.client_secret}")
private String CLIENT_SECRET;
@Value("${security.jwt.client_id}")
private String CLIENT_ID;
@Value("${security.jwt.grant_type_password}")
private String GRANT_TYPE_PASSWORD;
@Value("${security.jwt.grant_type_password}")
private String AUTHORIZATION_CODE;
@Value("${security.jwt.refresh_token}")
private String REFRESH_TOKEN;
@Value("${security.jwt.implicit}")
private String IMPLICIT;
@Value("${security.jwt.scope_read}")
private String SCOPE_READ;
@Value("${security.jwt.scope_write}")
private String SCOPE_WRITE;
@Value("${security.jwt.trust}")
private String TRUST;
@Value("${security.jwt.signin_key}")
private String SIGNIN_KEY;
@Value("${security.jwt.access_tokn_validity_seconds}")
private int ACCESS_TOKEN_VALIDITY_SECONDS;
@Value("${security.jwt.frefresh_tokn_validity_seconds}")
private int FREFRESH_TOKEN_VALIDITY_SECONDS;
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNIN_KEY);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
configurer
.inMemory()
.withClient(CLIENT_ID)
.secret(CLIENT_SECRET)
.authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN, IMPLICIT )
.scopes(SCOPE_READ, SCOPE_WRITE, TRUST)
.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
.authorities()
.refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore())
.authenticationManager(authenticationManager)
.accessTokenConverter(accessTokenConverter());
}
ResourceServerConfig:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Value("${security.oauth2.resource.resource_id}")
private String RESOURCE_ID;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
@Override
public void configure(HttpSecurity http) throws Exception {
/*
* here configure the security zone:
* the resource /oauth/token is public and not security
* the resource /user is private only for admin role
* any resources in the itaca are in secure zone and need use the token
*/
http
.headers().frameOptions().disable()
.and().authorizeRequests()
.antMatchers("/oauth/token", "/oauth/authorize**", "/public").permitAll()
.antMatchers("/user").access("hasRole('ADMIN')")
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler())
.and()
.formLogin() // if exist form login
.permitAll()
.and()
.logout() // if exist form or process logout
.permitAll();
}
}
SecurityConfig:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${security.jwt.signin_key}")
private String SIGNIN_KEY;
@Resource(name = "userService")
private UserDetailsService userDetailsService;
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(encoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers().frameOptions().disable()
.and().authorizeRequests()
.antMatchers("/oauth/token", "/oauth/authorize**", "/public").permitAll()
.antMatchers("/user").access("hasRole('ADMIN')")
.antMatchers("/api-docs/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.permitAll()
.and()
.logout()
.permitAll();
}
@Bean
public BCryptPasswordEncoder encoder(){
return new BCryptPasswordEncoder();
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNIN_KEY);
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;
}
}