Extract Currently Logged in User information from JWT token using Spring Security

后端 未结 2 1907
谎友^
谎友^ 2021-02-04 07:34

I have implemented JWT and LDAP Authentication using Spring Security Oauth2. It seems to be working fine and I can login with my LDAP credentials.

Now, there is one req

相关标签:
2条回答
  • 2021-02-04 08:21

    In your REST Service, add the OAuth2Authentication Class as an argument

    @RequestMapping(value = "/{id}/products", method = RequestMethod.POST)
        public ResourceResponse<String> processProducts(OAuth2Authentication auth) {
    

    Springboot will automatically map the logged-in user details to this object. Now, you can do the following to access the username

    auth.getPrincipal().toString()
    
    0 讨论(0)
  • 2021-02-04 08:33

    The first thing you need to do is store the user information inside the JWT when it is created, then you have to extract it when it is used. I had a similar situation and I solved it by extending both the TokenEnhancer and JwtAccessTokenConverter.


    I use the TokenEnhancer to embed my extended principal of type CustomUserDetailsinside the JWT additional information.

    public class CustomAccessTokenEnhancer implements TokenEnhancer {
    
        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            Authentication userAuthentication = authentication.getUserAuthentication();
            if (userAuthentication != null) {
                Object principal = authentication.getUserAuthentication().getPrincipal();
                if (principal instanceof CustomUserDetails) {
                    Map<String, Object> additionalInfo = new HashMap<>();
                    additionalInfo.put("userDetails", principal);
                    ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
                }
            }
            return accessToken;
        }
    }
    


    And then manually extract the extended principal when building the Authentication object when processing an authenticated request.

    public class CustomJwtAccessTokenConverter extends JwtAccessTokenConverter {
    
        @Override
        public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
            OAuth2Authentication authentication = super.extractAuthentication(map);
            Authentication userAuthentication = authentication.getUserAuthentication();
    
            if (userAuthentication != null) {
                LinkedHashMap userDetails = (LinkedHashMap) map.get("userDetails");
                if (userDetails != null) {
    
                    // build your principal here
                    String localUserTableField = (String) userDetails.get("localUserTableField");
                    CustomUserDetails extendedPrincipal = new CustomUserDetails(localUserTableField);
    
                    Collection<? extends GrantedAuthority> authorities = userAuthentication.getAuthorities();
    
                    userAuthentication = new UsernamePasswordAuthenticationToken(extendedPrincipal,
                            userAuthentication.getCredentials(), authorities);
                }
            }
            return new OAuth2Authentication(authentication.getOAuth2Request(), userAuthentication);
        }
    }
    


    and the AuthorizationServer configuration to tie it all together.

    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private UserDetailsService userDetailsService;
    
        @Autowired
        private DataSource dataSource;
    
        @Bean
        public JwtAccessTokenConverter accessTokenConverter() {
            CustomJwtAccessTokenConverter accessTokenConverter = new CustomJwtAccessTokenConverter();
            accessTokenConverter.setSigningKey("a1b2c3d4e5f6g");
            return accessTokenConverter;
        }
    
        @Bean
        public TokenStore tokenStore() {
            return new JwtTokenStore(accessTokenConverter());
        }
    
        @Bean
        @Primary
        public DefaultTokenServices tokenServices() {
            DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
            defaultTokenServices.setTokenStore(tokenStore());
            defaultTokenServices.setSupportRefreshToken(true);
            return defaultTokenServices;
        }
    
        @Bean
        public TokenEnhancer tokenEnhancer() {
            return new CustomAccessTokenEnhancer();
        }
    
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.jdbc(dataSource).passwordEncoder(passwordEncoder());
        }
    
        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
            tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), accessTokenConverter()));
            endpoints
                    .tokenStore(tokenStore())
                    .tokenEnhancer(tokenEnhancerChain)
                    .authenticationManager(authenticationManager)
                    .userDetailsService(userDetailsService);
        }
    
        @Override
        public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
            security.passwordEncoder(passwordEncoder());
            security.checkTokenAccess("isAuthenticated()");
        }
    }
    


    I am then able to access my extended principal in my resource controller like this

    @RestController
    public class SomeResourceController {
    
        @RequestMapping("/some-resource")
        public ResponseEntity<?> someResource(Authentication authentication) {
            CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal();
            return ResponseEntity.ok("woo hoo!");
        }
    
    }
    

    Hope this helps!

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