How do I map OAuth 2 token to UserDetails object in a resource server?

后端 未结 2 933
别跟我提以往
别跟我提以往 2021-02-02 01:13

I have 2 separate Spring Boot applications, one serving as an an OAuth 2 authorization server, and the other as resource server. I\'m using Spring\'s RemoteTokenServices

相关标签:
2条回答
  • To resolve the issue, let me go through a bit of architectural background first. The UserDetails object automatically mapped through the @AuthenticationPrincipal comes from the principal field of the active Authentication object. A resource server controller has access to an OAuth2Authencation object, which is a specialized instance of Authentication for Spring OAuth2 security framework, just by simply declaring it as part of the method parameters.

    public void controllerMethod(OAuth2Authentication authentication) {
        //controller definition
    }
    

    Knowing this, the problem now shifts to how to make sure that the getPrincipal() method in the Authentication object is an instance of my custom UserDetails class. The RemoteTokenServices I use in the resource server application uses an instance of AccessTokenConverter to interpret token details sent by the authorization server. By default, it uses DefaultAccessTokenConverter, which just sets the authentication principal as the username, which is a String. This converter makes use of UserAuthenticationConverter to convert the data coming from the authorization server into an instance of Authentication. This is what I needed to customize:

    DefaultAccessTokenConverter tokenConverter = new DefaultAccessTokenConverter();
    tokenConverter.setUserTokenConverter(new DefaultUserAuthenticationConverter() {
    
        @Override
        public Authentication extractAuthentication(Map<String, ?> map) {
            Authentication authentication = super.extractAuthentication(map);
            // User is my custom UserDetails class
            User user = new User();
            user.setSpecialKey(map.get("specialKey").toString());
            return new UsernamePasswordAuthenticationToken(user,
                    authentication.getCredentials(), authentication.getAuthorities());
        }
    
    });
    tokenServices.setAccessTokenConverter(tokenConverter);
    

    With all these set up, the @AuthenticationPrincipal mechanism now works as expected.

    0 讨论(0)
  • 2021-02-02 02:04

    Did you enable the AuthenticationPrincipalArgumentResolver, like following xml?

    <mvc:annotation-driven>
            <mvc:argument-resolvers>
                    <bean class="org.springframework.security.web.method.annotation.AuthenticationPrincipalArgumentResolver" />
            </mvc:argument-resolvers>
    </mvc:annotation-driven>
    

    And you need to implement the UserDetails to return your own CustomerUser object, then you can use the annotation to get principal directly.

    0 讨论(0)
提交回复
热议问题