web-dev-qa-db-ja.com

アクセストークンの発行中にユーザー情報を含めることはできますか?

一部のoauth2実装では、認証サーバーがアクセストークンを発行したときに返される応答に関する追加情報を見てきました。 spring-security-oauth2を使用してこれを達成する方法があるかどうか疑問に思っています。アクセストークンレスポンスにユーザー権限を含めることができれば、消費アプリケーションはユーザー権限を管理する必要はありませんが、ユーザーを独自のセキュリティコンテキストに設定し、独自のスプリングセキュリティを適用できます。チェック。

  1. アクセストークンの応答でその情報を取得するにはどうすればよいですか?
  2. Oauth2クライアント側でその情報をどのようにインターセプトし、セキュリティコンテキストに設定しますか?

別のオプションは、JWTトークンを使用し、適切な情報をクライアントアプリケーションと共有して、トークンからユーザー/権限を解析し、コンテキストに設定できるようにすることです。どのクライアントアプリケーションがこの情報にアクセスできるか(信頼できるアプリのみ)を制御したいので、これは私をより不快にさせます。

24
RutledgePaulV

次のようなカスタムTokenEnhancerを実装する必要があります。

public class CustomTokenEnhancer implements TokenEnhancer {

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

        additionalInfo.put("customInfo", "some_stuff_here");
        additionalInfo.put("authorities", user.getAuthorities());

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

        return accessToken;
    }

}

そして、対応するセッターと共にBeanとしてAuthorizationServerConfigurerAdapterに追加します

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    // Some autowired stuff here

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // @formatter:off
        endpoints
            // ...
            .tokenEnhancer(tokenEnhancer());
        // @formatter:on
    }

    @Bean
    @Primary
    public AuthorizationServerTokenServices tokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        // ...
        tokenServices.setTokenEnhancer(tokenEnhancer());
        return tokenServices;
    }

    // Some @Bean here like tokenStore

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

}

その後、コントローラで(たとえば)

@RestController
public class MyController {

    @Autowired
    private AuthorizationServerTokenServices tokenServices;

    @RequestMapping(value = "/getSomething", method = RequestMethod.GET)
    public String getSection(OAuth2Authentication authentication) {
        Map<String, Object> additionalInfo = tokenServices.getAccessToken(authentication).getAdditionalInformation();

        String customInfo = (String) additionalInfo.get("customInfo");
        Collection<? extends GrantedAuthority> authorities = (Collection<? extends GrantedAuthority>) additionalInfo.get("authorities");

        // Play with authorities

        return customInfo;
    }

}

私はJDBC TokenStoreを個人的に使用しているので、「自動配線されたもの」は@Autowired Datasource、PasswordEncoderなどに対応しています。

これが役に立てば幸いです!

50
Philippe

SpringのJwtAccessTokenConverterまたはDefaultAccessTokenConverterを使用している場合、カスタムCustomTokenEnhancer(最初の応答を参照)を追加して適用できます。 TokenEnhancerChainを次のように使用します。

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

    TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
    enhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(), accessTokenConverter()));

    endpoints.tokenStore(tokenStore())
            .tokenEnhancer(enhancerChain)
            .authenticationManager(authenticationManager);
}

@Bean
protected JwtAccessTokenConverter jwtTokenEnhancer() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("my_signing_key");
    return converter;
}

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

別の解決策は、SpringのJwtAccessTokenConverterを拡張し、カスタムクレームでenhance()メソッドをオーバーライドするカスタムTokenConverterを作成することです。

public class CustomTokenConverter extends JwtAccessTokenConverter {

@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

    final Map<String, Object> additionalInfo = new HashMap<>();
    additionalInfo.put("customized", "true");
    User user = (User) authentication.getPrincipal();
    additionalInfo.put("isAdmin", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()).contains("BASF_ADMIN"));
    ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);

    return super.enhance(accessToken, authentication);
    }
} 

その後:

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

    endpoints.tokenStore(tokenStore())
            .tokenEnhancer(customTokenEnhancer())
            .authenticationManager(authenticationManager);
}

@Bean public CustomTokenConverter customTokenEnhancer() {
    return new CustomTokenConverter();
}
19
jchrbrt

一緒に:

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

含める必要があります

@Bean
public DefaultAccessTokenConverter accessTokenConverter() {
    return new DefaultAccessTokenConverter();
}

そして、すべてをエンドポイント構成に追加します。

@Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints
                .tokenStore(tokenStore)
                .tokenEnhancer(tokenEnhancer())
                .accessTokenConverter(accessTokenConverter())
                .authorizationCodeServices(codeServices)
                .authenticationManager(authenticationManager)
        ;
    }

これがないと、CustomTokenEnhancerは機能しません。

3
Yaroslav
package com.security;

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

import org.springframework.security.core.userdetails.User;
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 org.springframework.stereotype.Component;

@Component
public class CustomTokenEnhancer implements TokenEnhancer {

        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken,
                        OAuth2Authentication authentication) {
                // TODO Auto-generated method stub
                User user = (User) authentication.getPrincipal();
        final Map<String, Object> additionalInfo = new HashMap<>();

        additionalInfo.put("customInfo", "some_stuff_here");
        additionalInfo.put("authorities", user.getAuthorities());

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

        return accessToken;
        }

}

Xml構成は次のとおりです。

<bean id="tokenEnhancer" class="com.security.CustomTokenEnhancer" />

<!-- Used to create token and and every thing about them except for their persistence that is reposibility of TokenStore (Given here is a default implementation) -->
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
  <property name="tokenStore" ref="tokenStore" />
  <property name="accessTokenValiditySeconds" value="30000000"></property>
  <property name="refreshTokenValiditySeconds" value="300000000"></property>
  <property name="supportRefreshToken" value="true"></property>
  <property name="clientDetailsService" ref="clientDetails"></property>
  <property name="tokenEnhancer" ref="tokenEnhancer" />
</bean>

これで、トークンに追加情報を追加できました。

3
harshlal028
  1. クラスファイルを作成するCustomTokenEnhancer
@Component
public class CustomTokenConverter extends JwtAccessTokenConverter {


    @Override
    public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {

        final Map<String, Object> additionalInfo = new HashMap<>();
        additionalInfo.put("customized", "true");
        User user = (User) authentication.getPrincipal();
        additionalInfo.put("role", user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
        ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);

        return super.enhance(accessToken, authentication);
    }
}
  1. 書かれたコードの下にAuthorizationServerConfigを貼り付けます
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    TokenEnhancerChain enhancerChain = new TokenEnhancerChain();
    enhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(),accessTokenConverter()));

    endpoints
        .tokenStore(tokenStore())
        .tokenEnhancer(customTokenEnhancer())
        .authenticationManager(authenticationManager);
}

@Bean
protected JwtAccessTokenConverter jwtTokenEnhancer() {
    JwtAccessTokenConverter converter=  new JwtAccessTokenConverter();
    converter.setSigningKey("my_signing_key");

    return converter;
}

@Bean
public CustomTokenConverter customTokenEnhancer() {
    return new CustomTokenConverter();
}

@Bean
public TokenStore tokenStore() {
    return new JdbcTokenStore(dataSource);
}
  1. 上記のコードを貼り付けた後、適切なライブラリをインポートします

カスタムトークンエンハンサーの出力応答。ここをクリック

0
Anjali K A

UserDetailsS​​erviceAutoConfigurationを除外すると、この問題が解決します。このような。 OAuth2リソースサーバーで役立つかもしれません。

@SpringBootApplication(exclude = [UserDetailsServiceAutoConfiguration::class])
class Application

fun main(args: Array<String>) {
    runApplication<Application>(*args)
}
0
Linolium