简体   繁体   中英

How to get Additional fields in the JWT token in security context of Resource Server

I am trying to implement spring security oauth2 in my application. The configuration is working perfectly except that I am not able to get additional fields of JWT token in the Resource Server Security Context object.

Here is My configuration:

Authorization server:

public class SpringSecurityConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetailsService());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.allowFormAuthenticationForClients().tokenKeyAccess("permitAll()")
                .checkTokenAccess("isAuthenticated()");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.userApprovalHandler(userApprovalHandler()).tokenServices(tokenServices())
                .clientDetailsService(clientDetailsService()).authenticationManager(authenticationManager).accessTokenConverter(tokenEnhancer());
    }

    @Bean
    public CustomTokenEnhancer accessTokenEnhancer() {
        CustomTokenEnhancer customTokenEnhancer = new CustomTokenEnhancer();
        return customTokenEnhancer;
    };

    @Bean
    public OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint() {
        OAuth2AuthenticationEntryPoint oauth2AuthenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        oauth2AuthenticationEntryPoint.setRealmName("test");
        return oauth2AuthenticationEntryPoint;
    }

    @Bean
    public OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint() {
        OAuth2AuthenticationEntryPoint clientAuthenticationEntryPoint = new OAuth2AuthenticationEntryPoint();
        clientAuthenticationEntryPoint.setRealmName("test/client");
        clientAuthenticationEntryPoint.setTypeName("Basic");
        return clientAuthenticationEntryPoint;
    }

    @Bean
    public OAuth2AccessDeniedHandler oauthAccessDeniedHandler() {
        return new OAuth2AccessDeniedHandler();
    }

    @Bean
    public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() {
        ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter = new ClientCredentialsTokenEndpointFilter();
        clientCredentialsTokenEndpointFilter.setAuthenticationManager(authenticationManager);
        return clientCredentialsTokenEndpointFilter;
    }

    @Bean
    public UnanimousBased accessDecisionManager() {
        List<AccessDecisionVoter<? extends Object>> AccessDecisionVoter = new ArrayList<AccessDecisionVoter<? extends Object>>();
        ScopeVoter scopeVoter = new ScopeVoter();
        RoleVoter roleVoter = new RoleVoter();
        AuthenticatedVoter authenticatedVoter = new AuthenticatedVoter();
        AccessDecisionVoter.add(scopeVoter);
        AccessDecisionVoter.add(roleVoter);
        AccessDecisionVoter.add(authenticatedVoter);
        UnanimousBased accessDecisionManager = new UnanimousBased(AccessDecisionVoter);
        return accessDecisionManager;
    }

    @Bean
    public ClientDetailsUserDetailsService clientDetailsUserDetailsService() throws Exception {
        ClientDetailsUserDetailsService clientDetailsUserDetailsService = new ClientDetailsUserDetailsService(
                clientDetailsService());
        return clientDetailsUserDetailsService;
    }

    @Bean
    public JwtAccessTokenConverter tokenConverter() {
        final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        final CustomTokenSignKeyGenerator signKey = new CustomTokenSignKeyGenerator();
        converter.setSigningKey(signKey.getSecurityKey());
        return converter;
    }

    @Bean
    public JwtAccessTokenConverter tokenEnhancer() {
        JwtAccessTokenConverter tokenEnhancer = new JwtAccessTokenConverter();
        final CustomTokenSignKeyGenerator signKey = new CustomTokenSignKeyGenerator();
        tokenEnhancer.setSigningKey(signKey.getSecurityKey());
        tokenEnhancer.setAccessTokenConverter(tokenConverter());
        return tokenEnhancer;
    }

    @Bean
    public TokenEnhancerChain tokenEnhancerChain() {
        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        List<TokenEnhancer> delegates = new ArrayList<TokenEnhancer>();
        delegates.add(tokenEnhancer());
        delegates.add(accessTokenEnhancer());
        tokenEnhancerChain.setTokenEnhancers(delegates);
        return tokenEnhancerChain;
    }

    @Bean
    public DefaultOAuth2RequestFactory requestFactory() throws Exception {
        DefaultOAuth2RequestFactory defaultOAuth2RequestFactory = new DefaultOAuth2RequestFactory(
                clientDetailsService());
        return defaultOAuth2RequestFactory;
    }

    @Bean
    public ClientCredentialsTokenGranter tokenGranter() throws Exception {
        AuthorizationServerTokenServices tokenServices = tokenServices();
        OAuth2RequestFactory requestFactory = requestFactory();
        ClientCredentialsTokenGranter clientCredentialsTokenGranter = new ClientCredentialsTokenGranter(tokenServices,
                clientDetailsService(), requestFactory);
        return clientCredentialsTokenGranter;
    }

    @Bean
    public JwtTokenStore tokenStore() {
        JwtTokenStore tokenStore = new JwtTokenStore(tokenEnhancer());
        return tokenStore;
    }

    @Bean
    public DefaultTokenServices tokenServices() throws Exception {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setSupportRefreshToken(true);
        defaultTokenServices.setAccessTokenValiditySeconds(300);
        defaultTokenServices.setClientDetailsService(clientDetailsService());
        defaultTokenServices.setTokenEnhancer(tokenEnhancerChain());
        return defaultTokenServices;
    }

    @Bean
    public DefaultOAuth2RequestFactory oAuth2RequestFactory() throws Exception {
        DefaultOAuth2RequestFactory defaultOAuth2RequestFactory = new DefaultOAuth2RequestFactory(
                clientDetailsService());
        return defaultOAuth2RequestFactory;
    }

    @Bean
    public TokenStoreUserApprovalHandler userApprovalHandler() throws Exception {
        TokenStoreUserApprovalHandler tokenStoreUserApprovalHandler = new TokenStoreUserApprovalHandler();
        tokenStoreUserApprovalHandler.setRequestFactory(requestFactory());
        tokenStoreUserApprovalHandler.setTokenStore(tokenStore());
        return tokenStoreUserApprovalHandler;
    }

    @Bean
    public ClientDetailsService clientDetailsService() throws Exception {
        return new InMemoryClientDetailsServiceBuilder().withClient("restapp").secret("restapp")
                .authorizedGrantTypes("password", "authorization_code").scopes("read").authorities("ROLE_USER")
                .accessTokenValiditySeconds(3600).and().build();
    }

}

Custom Token Enhancer:

public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
        //featureLogger.debug("start of enhance method in CustomTokenEnhancer");
        LdapUserDetails userDetails = (LdapUserDetails) authentication.getPrincipal();
        final Map<String, Object> additionalInfo = new HashMap<>();

        additionalInfo.put(PharmacyOAuthConstants.USER_NAME, userDetails.getUsername());
        additionalInfo.put(PharmacyOAuthConstants.STORE_ID, "hysjg");
        additionalInfo.put(PharmacyOAuthConstants.USER_ROLES, userDetails.getAuthorities());

        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
        //featureLogger.debug("end of enhance method in CustomTokenEnhancer");
        return accessToken;
        //return super.enhance(accessToken, authentication);
    }

Resource Server:

public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Autowired
    CustomTokenSignKeyGenerator customTokenSignKeyGenerator;

    /**
     * This method is used to intercept and verify whether all the requests for
     * accessing the resource are authenticated by having a valid access token
     */
    @Override
    public void configure(final HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).and().authorizeRequests()
                .antMatchers("/core/**").fullyAuthenticated();
                //.anyRequest().permitAll();//.fullyAuthenticated();

    }

    /**
     * Reference to a CheckTokenServices that can validate an OAuth2AccessToken
     */
    @Override
    public void configure(ResourceServerSecurityConfigurer config) {
        try {
            config.tokenServices(tokenServices());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    /**
     * This Method is used to store the updated JWT in token store
     * @return TokenStore
     */
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(tokenConverter());
    }

    /**
     * This method is used to add custom signature key generated by using key store to JWT signature part
     * @return JwtAccessTokenConverter
     */
    @Bean
    public JwtAccessTokenConverter tokenConverter() {
        final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        final CustomTokenSignKeyGenerator signKey = new CustomTokenSignKeyGenerator();
        converter.setSigningKey(signKey.getSecurityKey());
        return converter;
    }

    @Bean
    public JwtAccessTokenConverter tokenEnhancer() {
        JwtAccessTokenConverter tokenEnhancer = new JwtAccessTokenConverter();
        final CustomTokenSignKeyGenerator signKey = new CustomTokenSignKeyGenerator();
        tokenEnhancer.setSigningKey(signKey.getSecurityKey());
        tokenEnhancer.setAccessTokenConverter(tokenConverter());
        return tokenEnhancer;
    }


    /**This method will return the token services required to verify the token received
     * @return defaultTokenServices
     */
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
        defaultTokenServices.setTokenStore(tokenStore());
        defaultTokenServices.setTokenEnhancer(tokenEnhancer());
        return defaultTokenServices;
    }


In the Authentication object I am always seeing null value for decoded details object.
@Autowired
private AuthorizationServerTokenServices tokenServices;

@Autowired
private TokenStore tokenStore;

@PreAuthorize("hasAuthority('ROLE_ADMIN') and #oauth2.hasScope('READ')")
@GetMapping()
public List<Account> getAll(OAuth2Authentication authentication) {

    OAuth2AuthenticationDetails auth2AuthenticationDetails = (OAuth2AuthenticationDetails) authentication.getDetails();
    Map<String, Object> details = tokenStore.readAccessToken(auth2AuthenticationDetails.getTokenValue()).getAdditionalInformation();
    String storeID = (String) details.get(PharmacyOAuthConstants.STORE_ID);

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM