web-dev-qa-db-fra.com

puis-je inclure des informations utilisateur lors de l'émission d'un jeton d'accès?

J'ai vu dans certaines implémentations de oauth2 des informations supplémentaires sur la réponse renvoyée par le serveur d'autorisations lorsqu'il émet des jetons d'accès. Je me demande s'il existe un moyen d'y parvenir en utilisant spring-security-oauth2. J'aimerais pouvoir inclure des autorités d'utilisateur dans la réponse au jeton d'accès afin que mes applications consommatrices n'aient pas besoin de gérer les autorisations d'utilisateur mais puissent toujours définir l'utilisateur dans leurs propres contextes de sécurité et appliquer l'une de leurs propres sources. chèques.

  1. Comment pourrais-je obtenir cette information sur la réponse du jeton d'accès?
  2. Comment pourrais-je intercepter ces informations côté client oauth2 et les définir dans le contexte de sécurité?

Je suppose qu'une autre option consisterait à utiliser des jetons JWT et à partager les informations appropriées avec les applications clientes afin qu'elles puissent analyser l'utilisateur/les autorités du jeton et le définir en fonction du contexte. Cela me rend encore plus mal à l'aise, car je préférerais savoir quelles applications clientes pourraient avoir accès à ces informations (applications de confiance uniquement) et, autant que je sache, le serveur d'autorisation et le serveur de ressources devraient savoir comment analyser les jetons JWT.

18
RutledgePaulV

Vous devrez implémenter un TokenEnhancer personnalisé comme ceci:

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

}

et l'ajouter à votre AuthorizationServerConfigurerAdapter en tant que bean avec les paramètres correspondants

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

}

puis dans un contrôleur (par exemple)

@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;
    }

}

J'utilise personnellement un TokenStore JDBC, donc mes "éléments auto-câblés ici" correspondent à des sources de données @Autowired, PasswordEncoder et autres.

J'espère que cela a aidé!

42
Philippe

Si vous utilisez les variables JwtAccessTokenConverter ou DefaultAccessTokenConverter de Spring, vous pouvez ajouter votre CustomTokenEnhancer personnalisé (voir la première réponse) et l'appliquer à l'aide de TokenEnhancerChain comme ceci: 

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

Une autre solution consiste à créer un TokenConverter personnalisé qui étend la variable JwtAccessTokenConverter de Spring et à remplacer la méthode enhan () par vos revendications personnalisées.

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

Et alors:

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

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

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

Ensemble avec: 

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

Vous devez inclure

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

et ajoutez tout à la configuration des noeuds finaux:

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

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

Sans cela, votre CustomTokenEnhancer ne fonctionnera pas.

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

}

Voici la configuration 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>

C'est ainsi que j'ai pu ajouter des informations supplémentaires au jeton.

3
harshlal028
  1. créer un fichier de classe CustomTokenEnhancer

      @Component
    

    public class CustomTokenConverter étend JwtAccessTokenConverter {

    @Override Public OAuth2AccessToken améliorer (OAuth2AccessToken accessToken, authentification OAuth2Authentication) {

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

} </ pre> 2. coller le code écrit ci-dessous dans AuthorizationServerConfig 

  
 @Passer outre
 public void configure (noeuds finaux AuthorizationServerEndpointsConfigurer) lève une 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);
}

</ pre> 

  1. importer les bibliothèques appropriées après avoir collé les codes ci-dessus

réponse en sortie de Custom Token Enhancer..click here

0
Anjali K A