web-dev-qa-db-ja.com

access_token JWTにデータを追加する方法

実際にaccess_tokenで生成されるgrant_type=passwordであるJWTトークンに新しいフィールドを追加しようとしています。付与タイプがpasswordのみの場合は、フィールドを追加したい。

カスタムトークンエンハンサーを実装すると、oauth login apiの応答本文に新しいフィールドが追加されます。ただし、これらの新しいフィールドはaccess_token JWT内にのみ必要です。

例えば。:

access_tokenをデコードするとき、オブジェクトは

{
  "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"
}

CustomTokenEnhancerを実装すると、ログインの応答本文にnewFieldリストが追加されます。

{
    "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;
    }
}

access_tokenpasswordの場合、grant_type JWTを変更できますか?

11
Eniss

あなたの質問は以下に非常に類似/同じですSO thread

Spring OAuth 2 + JWT Including additional info JUST in access token

少しわかりやすくします。二つあります

  • トークンを拡張してより多くの情報を含めるアクセストークンエンハンサー
  • トークンをAPIに表示される出力に変換するトークンコンバーター

だからあなたが欲しいものは以下です

  • アクセストークンエンハンサーは追加のプロパティを見るはずです
  • アクセストークンコンバーターは追加のプロパティを表示しない

以下は実際に使用したクラスです

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();
//    }

}

元のコードは以下にあります

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

私の変更は含まれていませんが、上記のコードで十分です

テスト

Body

ご覧のとおり、ボディには追加のプロパティが含まれていません

Access token

ご覧のとおり、アクセストークンには追加のプロパティがあります。また、passwordgrant_typeのみの要件を満たしている

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