Search code examples
spring-security-oauth2auth0

Override UserAuthenticationConverter for JWT OAuth Tokens


I am trying to create a spring resource server secured with oauth2.

I am using auth0 for my auth2 service, and I have an api and client configured with scopes.

I have a resource server that mostly works. It is secured, and I can use @EnableGlobalMethodSecurity and @PreAuthorize("#oauth2.hasScope('profile:read')") to limit access to tokens with that scope.

However, when I try to get the Principal or the OAuth2Authentication they are both null. I've configured the resource server to use the JWK key-set-uri.

I suspect that this has to do with the DefaultUserAuthenticationConverter trying to read the the 'user_name' claim form the JWT, but it needs to be reading it from the 'sub' claim, and I don't know how to change this behaviour.


Solution

  • First create a UserAuthenticationConverter:

    public class OidcUserAuthenticationConverter implements UserAuthenticationConverter {
    
        final String SUB = "sub";
    
        @Override
        public Map<String, ?> convertUserAuthentication(Authentication userAuthentication) {
            throw new UnsupportedOperationException();
        }
    
        @Override
        public Authentication extractAuthentication(Map<String, ?> map) {
            if (map.containsKey(SUB)) {
                Object principal = map.get(SUB);
                Collection<? extends GrantedAuthority> authorities = null;
                return new UsernamePasswordAuthenticationToken(principal, "N/A", authorities);
            }
            return null;
        }
    }
    

    Then configure spring to use it like so:

    @Configuration
    public class OidcJwkTokenStoreConfiguration {
        private final ResourceServerProperties resource;
    
        public OidcJwkTokenStoreConfiguration(ResourceServerProperties resource) {
            this.resource = resource;
        }
    
        @Bean
        public TokenStore jwkTokenStore() {
            DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
            tokenConverter.setUserTokenConverter(new OidcUserAuthenticationConverter());
            return new JwkTokenStore(this.resource.getJwk().getKeySetUri(), tokenConverter);
        }
    }