web-dev-qa-db-fra.com

Comment ajouter plus de données dans access_token JWT

J'essaie d'ajouter de nouveaux champs dans le jeton JWT qui est en fait access_token qui est généré avec grant_type=password. Je souhaite ajouter d'autres champs si le type de subvention est uniquement password.

Si j'implémente un optimiseur de jeton personnalisé, il ajoute de nouveaux champs dans le corps de réponse de oauth api de connexion. Mais je n'ai besoin que de ces nouveaux champs dans access_token JWT.

par exemple.:

lors du décodage access_token, L'objet doit provenir de

{
  "user_name": "uuid",
  "scope": [
    "trust"
  ],
  "exp": 1522008499,
  "authorities": [
    "USER"
  ],
  "jti": "9d827f63-99ba-4fc1-a838-bc74331cf660",
  "client_id": "myClient"
}

à

{
  "user_name": "uuid",
  "newField": [
    {
      "newFieldChild": "1",
    },
    {
      "newFieldChild": "2",
    }
  ],
  "scope": [
    "trust"
  ],
  "exp": 1522008499,
  "authorities": [
    "USER"
  ],
  "jti": "9d827f63-99ba-4fc1-a838-bc74331cf660",
  "client_id": "myClient"
}

L'implémentation de CustomTokenEnhancer ajoute la liste newField dans le corps de réponse de la connexion:

{
    "access_token": "jwt-access_token",
    "token_type": "bearer",
    "refresh_token": "jwt-refresh_token",
    "expires_in": 299999,
    "scope": "trust",
    "jti": "b23affb3-39d3-408a-bedb-132g6de15d7",
    "newField": [
      {
        "newFieldChild": "1",
      },
      {
        "newFieldChild": "2",
      }
    ]
}

CustomTokenEnhancer:

public class CustomTokenEnhancer implements TokenEnhancer {
    @Override
    public OAuth2AccessToken enhance(
            OAuth2AccessToken accessToken,
            OAuth2Authentication authentication) {
        Map<String, Object> additionalInfo = new HashMap<>();
        Map<String, String> newFields = ....;
        additionalInfo.put("newField", newFields);
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
        return accessToken;
    }
}

est-il possible de modifier access_token JWT si grant_type est password?

11
Eniss

Votre question est assez similaire/identique à ci-dessous SO thread

Spring OAuth 2 + JWT Inclusion d'informations supplémentaires JUST dans le jeton d'accès

Je vais juste le rendre un peu plus facile à comprendre. Il y a deux choses

  • Un améliorateur de jeton d'accès qui améliore votre jeton pour inclure plus d'informations
  • Un convertisseur de jeton qui convertit le jeton en sortie que vous voyez dans l'API

Donc ce que vous voulez c'est en dessous

  • L'optimiseur de jeton d'accès devrait voir les propriétés supplémentaires
  • Le convertisseur de jeton d'accès ne doit pas voir les propriétés supplémentaires

Voici la classe que j'ai utilisée

package org.baeldung.config;

import Java.util.Arrays;
import Java.util.HashMap;
import Java.util.Map;

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.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
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.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
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;

import static org.Apache.commons.lang3.RandomStringUtils.randomAlphabetic;

@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfigJwt extends AuthorizationServerConfigurerAdapter {

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

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

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
            .withClient("sampleClientId")
            .authorizedGrantTypes("implicit")
            .scopes("read", "write", "foo", "bar")
            .autoApprove(false)
            .accessTokenValiditySeconds(3600)

            .and()
            .withClient("fooClientIdPassword")
            .secret("secret")
            .authorizedGrantTypes("password", "authorization_code", "refresh_token")
            .scopes("foo", "read", "write")
            .accessTokenValiditySeconds(3600)
            // 1 hour
            .refreshTokenValiditySeconds(2592000)
            // 30 days

            .and()
            .withClient("barClientIdPassword")
            .secret("secret")
            .authorizedGrantTypes("password", "authorization_code", "refresh_token")
            .scopes("bar", "read", "write")
            .accessTokenValiditySeconds(3600)
            // 1 hour
            .refreshTokenValiditySeconds(2592000) // 30 days
        ;
    }

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

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

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        final JwtAccessTokenConverter converter = new JwtAccessTokenConverter(){
            @Override
            public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
                if(authentication.getOAuth2Request().getGrantType().equalsIgnoreCase("password")) {
                    final Map<String, Object> additionalInfo = new HashMap<String, Object>();
                    additionalInfo.put("organization", authentication.getName() + randomAlphabetic(4));
                    ((DefaultOAuth2AccessToken) accessToken)
                            .setAdditionalInformation(additionalInfo);
                }
                accessToken = super.enhance(accessToken, authentication);
                ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(new HashMap<>());
                return accessToken;
            }
        };
        // converter.setSigningKey("123");
        final KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("mytest.jks"), "mypass".toCharArray());
        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("mytest"));
        return converter;
    }

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

}

Le code d'origine est ci-dessous

https://github.com/Baeldung/spring-security-oauth

N'inclut pas mes modifications, mais le code ci-dessus est suffisant

Test

Body

Comme vous pouvez le voir, le corps ne contient pas les propriétés supplémentaires

Access token

Comme vous pouvez le voir, le jeton d'accès possède les propriétés supplémentaires. Aussi votre exigence pour seulement grant_type comme password est rencontré par

if(authentication.getOAuth2Request().getGrantType().equalsIgnoreCase("password")) {
9
Tarun Lalwani