2017-09-25 3 views
1

Ich bin in der Lage, zusätzliche Informationen in das Access-Token zu integrieren, die meinen eigenen TokenEnhancer implementieren, aber solche Informationen sind doppelt enthalten. Eins im codierten access_token und das andere in der Authentifizierungsserverantwort.Spring OAuth 2 + JWT mit zusätzlichen Informationen JUST in Access-Token

Lange Rede kurzer Sinn! Ich bitte ein Zugriffstoken mit richtigen Anmeldeinformationen, und ich erhalte diese Antwort:

{ 
    "access_token" : "eyJhbGciOiJSUzI1NiJ9.eyJjbGllbnRJZCI6Ik1ZX0NVU1RPTV9JTkZPX0NMSUVOVCIsInVzZXJfbmFtZSI6IlVTRVIiLCJzY29wZSI6WyJGT08iXSwiZXhwIjoxNTA2MzkwOTM5LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiZjJkYWFkM2ItYzkzOC00ZjExLWI3ODctMzExZDdlNjYzYzhhIiwiY2xpZW50X2lkIjoid2ViX2FwcCJ9.IdgYRxwZGRPR97nxHpAcJXNWDTShQE1tsg9NsBwlOk8eDWE1B-mjfGTaKiyTO1-m9GBpXnxt2PaOV7AbdLsCZ5xLPUR0_5ehuNB6WCXLSkdac5xbw-rmNdJHTe9gLJizOZAKF6J-_Xo9OOQISKBqliY5vo5y0btqIw4CX6-ukYoWZmwHThwnAsEA_PqGuEXsbXMGz-vqJaSVpvJeEOBNL0KOh-cNxc0ft-rJ3snjPerN_efAiZdFkzxdCeuoGmZvSyHRjYR8kQ3ZqZ5MOunw9YuTvidL1IK5TODHQ2BjiCTpbgDlYx-Oh5UxcYNrPOhD-tBjRuuqDSz8K6ddpke4RQ", 
    "token_type" : "bearer", 
    "refresh_token" : "eyJhbGciOiJSUzI1NiJ9.eyJjbGllbnRJZCI6Ik1ZX0NVU1RPTV9JTkZPX0NMSUVOVCIsInVzZXJfbmFtZSI6IlVTRVIiLCJzY29wZSI6WyJGT08iXSwiYXRpIjoiZjJkYWFkM2ItYzkzOC00ZjExLWI3ODctMzExZDdlNjYzYzhhIiwiZXhwIjoxNTA4OTM5NzM5LCJhdXRob3JpdGllcyI6WyJST0xFX1VTRVIiXSwianRpIjoiOGU2Zjc0OTEtMmQ3MC00NTUwLThhMDgtZjk0YjkzYTVkYWZmIiwiY2xpZW50X2lkIjoid2ViX2FwcCJ9.MqwMrYrofu7pUQu2mF33__h6M4OWSRrQ-lc8JzTn0DkpJ6a3-yjnjjppZ9fs3KBz_lpRIO8jo--eId449rEjP4M3_9lDRSW9_HyBAvd57OtyUHa5SPM9prD6ReXGCyiIw2gO07euIf-Vp4UHsjoKK0MdtfMmFIWms1JMGFBmzBha8kqKaMxKzppGy-jVdP7384K9oovD20H-NubjScfoO2Crp1cTM-SXc-0v6kwB1qV-cI6HKXmbkoFhbH2bL_nRvXTkLYI-UvRNTNLHzqhcqztLTrszcWa2BjNU2IofsNByFS8BHTDV1vu0BqZA4kfNCJcFJ89tBDt2L8vfFkYezQ", 
    "expires_in" : 43199, 
    "scope" : "FOO", 
    "clientId" : "MY_CUSTOM_INFO_CLIENT", 
    "jti" : "f2daad3b-c938-4f11-b787-311d7e663c8a" 
} 

So kann ich sehen, clientId in der Antwort enthalten ... Jetzt kopiere ich meine access_token und ich dekodiert in: https://jwt.io/

Und in der Nutzlast ist auch die clientId enthalten ...

Meine Frage ist: Wie kann ich die zusätzlichen Informationen aus der Serverantwort entfernen und es nur in den Token (access_token und refresh_token) lassen.

finden Sie unter dem Code:

import java.util.Arrays; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.Primary; 
import org.springframework.core.io.ClassPathResource; 
import org.springframework.security.authentication.AuthenticationManager; 
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 
import org.springframework.security.oauth2.provider.token.DefaultTokenServices; 
import org.springframework.security.oauth2.provider.token.TokenEnhancer; 
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; 
import org.springframework.security.oauth2.provider.token.TokenStore; 
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore; 
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory; 

@Configuration 
@EnableAuthorizationServer 
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { 

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

    @Override 
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 
     TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); 
     tokenEnhancerChain.setTokenEnhancers(
        Arrays.asList(tokenEnhancer(), accessTokenConverter())); 
     endpoints 
       .tokenStore(tokenStore()) 
       .authenticationManager(authenticationManager) 
       .tokenEnhancer(tokenEnhancerChain); 
    } 
    @Override 
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 

     clients.inMemory() 
      .withClient("web_app") 
      .secret("web_app123") 
      .scopes("FOO") 
      .autoApprove(true) 
      .authorities("FOO_READ", "FOO_WRITE") 
      .authorizedGrantTypes("refresh_token", "password"); 
} 
    @Bean 
    public TokenStore tokenStore() { 
     return new JwtTokenStore(accessTokenConverter()); 
    } 

    @Bean 
    public JwtAccessTokenConverter accessTokenConverter() { 
     JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 
     KeyStoreKeyFactory keyStoreKeyFactory = 
      new KeyStoreKeyFactory(new ClassPathResource("mykey.jks"), "mykey123".toCharArray()); 
     converter.setKeyPair(keyStoreKeyFactory.getKeyPair("mykey")); 
     return converter; 
    } 

    @Bean 
    @Primary 
    public DefaultTokenServices tokenServices() { 
     DefaultTokenServices defaultTokenServices = new DefaultTokenServices(); 
     defaultTokenServices.setTokenStore(tokenStore()); 
     defaultTokenServices.setSupportRefreshToken(true); 
     return defaultTokenServices; 
    } 

    @Bean 
    public TokenEnhancer tokenEnhancer() { 
     return new CustomTokenEnhancer(); 
    } 
} 

Und mein CustomTokenEnhancer:

import java.util.HashMap; 
import java.util.Map; 

import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; 
import org.springframework.security.oauth2.common.OAuth2AccessToken; 
import org.springframework.security.oauth2.provider.OAuth2Authentication; 
import org.springframework.security.oauth2.provider.token.TokenEnhancer; 

import com.mapflow.ms.security.service.UserDetailInfo; 

public class CustomTokenEnhancer implements TokenEnhancer { 

    @Override 
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, 
      OAuth2Authentication authentication) { 
     UserDetailInfo user = (UserDetailInfo) authentication.getPrincipal(); 
     final Map<String, Object> additionalInfo = new HashMap<String, Object>(); 

     additionalInfo.put("clientId", user.getClientId()); 

     ((DefaultOAuth2AccessToken) accessToken) 
       .setAdditionalInformation(additionalInfo); 

     return accessToken; 
    } 
} 

Antwort

1

Nach einer Weile habe ich es herausgefunden. JwtAccessTokenConverter implementiert TokenEnhaner auch. Zuerst wird CustomTokenEnhaner.enhance aufgerufen, einschließlich der zusätzlichen Informationen. Dann JwtAccessTokenConverter.enhance, Codierung der AccessToken von CustomTokenEnhaner.enhance und zusätzliche Informationen zu der Antwort hinzufügen. Die Idee ist DefaultOAuth2AccessToken.additionalInformation initialisieren ist einmal in der access_token codiert. Die Lösung ist:

Zuerst lassen CustomTokenEnhancerJwtAccessTokenConverter erstreckt, außer Kraft setzen enhance, fügen weitere Informationen, rufen Sie enhance aus dem übergeordneten und initialisieren DefaultOAuth2AccessToken.additionalInformation:

public class CustomTokenConverter extends JwtAccessTokenConverter { 

    @Override 
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, 
      OAuth2Authentication authentication) { 
     if(authentication.getOAuth2Request().getGrantType().equalsIgnoreCase("password")) { 
      UserDetailInfo user = (UserDetailInfo) authentication.getPrincipal(); 
      final Map<String, Object> additionalInfo = new HashMap<String, Object>(); 

      additionalInfo.put("clientId", user.getClientId()); 

      ((DefaultOAuth2AccessToken) accessToken) 
        .setAdditionalInformation(additionalInfo);  
     } 
     accessToken = super.enhance(accessToken, authentication); 
     ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(new HashMap<>()); 
     return accessToken; 
    } 
} 

Und letzte Schritt wäre die

@Bean 
    public JwtAccessTokenConverter accessTokenConverter() { 
     JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); 
     KeyStoreKeyFactory keyStoreKeyFactory = 
      new KeyStoreKeyFactory(new ClassPathResource("mykey.jks"), "mykey123".toCharArray()); 
     converter.setKeyPair(keyStoreKeyFactory.getKeyPair("mykey")); 
     return converter; 
    } 
bean löschen

Und fügen Sie den Schlüssel zum CustomTokenEnhancer

hinzu

Das wäre es.

Verwandte Themen