I've a rich web (react based) front end application that sends request to a backend ResourceServer application. The requests are sent with JWT in the header for authentication. My setup does authentication against an Okta Authorization Server and retrieves Groups/Authorities from a separate service.
I have the backend server setup as a Springboot app with Spring Security Oauth2 resource server @EnableResourceServer
@Configuration
@EnableResourceServer
public class SecurityConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception{
http.requestMatchers().antMatchers("/api/**")
.and()
.authorizeRequests().anyRequest().authenticated();
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenServices(tokenServices()).resourceId("my-okta-resource-server-client-id");
}
@Bean
@Primary
public DefaultTokenServices tokenServices() throws Exception {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore());
return tokenServices;
}
@Bean
public TokenStore tokenStore() throws Exception {
return new JwkTokenStore("https://my-org.oktapreview.com/oauth2/my-auth-server/v1/keys");
}
With this setup I'm able to validate the JWT
token alright using the JwkTokenStore
implementation (It internally uses JwkVerifyingJwtAccessTokenConverter
to verify the Json Web Keyset from the keys uri supplied). However I'm unable to configure it to either
Authentication
. It only looks at the user_name claim, I'd like to use email or other claims on there.DefaultUserAuthenticationConverter
which encapsulates a UserDetailsService
is embedded deep within. This I need to lookup authorities the user is setup with in a separate rest service. Spring-security-oauth2's JWK related implementation seems closed with most of the JWKs
verification related classes not being public.
What's a good way to utilize the token verification provided by JwkTokenStore
and also be able to have your own user details in there to load authorities.
Software versions in use: Springboot 1.5.2.RELEASE, spring-security-core:4.2.3, spring-security-oauth2:2.0.14,
You should use the so called DefaultAccessTokenConverter
to extract these extra claims and add it to an OAuth2Authentication
object.
You can @Autowire
the CustomAccessTokenConverter
into your ResourceServerConfiguration
class and then set it to your JwtTokenStore()
configuration.
ResourceServerConfiguration:
@Autowired
private CustomAccessTokenConverter yourCustomAccessTokenConverter;
@Override
public void configure(final ResourceServerSecurityConfigurer config) {
config.tokenServices(tokenServices()).resourceId(resourceId);
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(jwkTokenStore());
return defaultTokenServices;
}
@Bean
public TokenStore jwtTokenStore() throws Exception {
return new JwkTokenStore("https://my-org.oktapreview.com/oauth2/my-auth-server/v1/keys", accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setAccessTokenConverter(yourCustomAccessTokenConverter);
return converter;
}
The CustomAccessTokenConverter can be configured, so that the custom claims get extracted here.
CustomAccessTokenConverter:
@Component
public class CustomAccessTokenConverter extends DefaultAccessTokenConverter {
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> claims) {
OAuth2Authentication authentication = super.extractAuthentication(claims);
authentication.setDetails(claims);
return authentication;
}
}
Afterwards you should be able to access the claims via the OAuth2Authentication
object.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With