web-dev-qa-db-fra.com

Spring Boot 2.0.0 + OAuth2

Spring Boot 2 + Sping Security OAuth2 prend-il en charge l’annotation @AuthorizationServer? À la lecture des notes de publication, certaines choses n'ont pas été reportées: 

Support Oauth2

Voici la section pertinente de mon build.grade:

Serveur d'authentification

// security
compile "org.springframework.boot:spring-boot-starter-security:${springBootVersion}"
// oauth
// https://mvnrepository.com/artifact/org.springframework.security.oauth/spring-security-oauth2
compile "org.springframework.security.oauth:spring-security-oauth2:2.2.1.RELEASE"

Serveur client

// support for Oauth2 user token services not yet migrated into Spring Boot 2.0
compile "org.springframework.security.oauth.boot:spring-security-oauth2-autoconfigure:2.0.1.BUILD-SNAPSHOT"

Et pour le moment, mes points d'extrémité Authorization Server Oauth2 renvoient un 401 lorsque j'essaie de transmettre un identifiant client et un secret client en tant que Basic Authentication à /oauth/token. Passer un nom d'utilisateur et un mot de passe donne un chemin de code différent. Il semble donc que les filtres OAuth ne sont pas tout à fait alignés.

J'ai aussi trouvé ceci aussi: Spring Boot 2 Changements de démarrage OAuth2 .

Y a-t-il eu une mise à jour de la configuration ou ai-je besoin d'un autre ensemble de dépendances de niveaux pour restaurer le serveur d'autorisation à son état précédent?

Merci!


METTRE À JOUR

Je voulais fermer la boucle sur cette question. En plus de chiffrer les secrets du client. Le problème RedisTokenStore a également été résolu à partir de Spring OAuth 2.3.2: Spring OAuth 2.3.2

3
false_memories

Spring Security 5 utilise un stockage de mot de passe modernisé, voir OAuth2 Autoconfig :

Si vous utilisez votre propre configuration de serveur d'autorisation pour configurer la liste des clients valides via une instance de ClientDetailsServiceConfigurer, comme indiqué ci-dessous, notez que les mots de passe que vous configurez ici sont soumis au stockage de mots de passe modernisé fourni avec Spring Security 5. 

Pour résoudre votre problème, voir Spring Security Reference :

Dépannage

L'erreur suivante se produit lorsqu'un des mots de passe stockés n'a pas d'identifiant, comme décrit dans la section intitulée «Format de stockage du mot de passe».

Java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
     at org.springframework.security.crypto.password.DelegatingPasswordEncoder$UnmappedIdPasswordEncoder.matches(DelegatingPasswordEncoder.Java:233)
     at org.springframework.security.crypto.password.DelegatingPasswordEncoder.matches(DelegatingPasswordEncoder.Java:196)

Le moyen le plus simple de résoudre l'erreur consiste à indiquer explicitement la variable PasswordEncoder avec laquelle les mots de passe sont codés. Le moyen le plus simple de le résoudre consiste à comprendre comment vos mots de passe sont actuellement stockés et à fournir explicitement la bonne variable PasswordEncoder. Si vous migrez depuis Spring Security 4.2.x, vous pouvez revenir au comportement précédent en exposant un bean NoOpPasswordEncoder. Par exemple, si vous utilisez la configuration Java, vous pouvez créer une configuration ressemblant à ceci:

Le retour à NoOpPasswordEncoder n'est pas considéré comme sécurisé. Vous devriez plutôt migrer vers DelegatingPasswordEncoder pour prendre en charge le codage sécurisé des mots de passe.

@Bean
public static NoOpPasswordEncoder passwordEncoder() {
    return NoOpPasswordEncoder.getInstance();
}

si vous utilisez la configuration XML, vous pouvez exposer une PasswordEncoder avec l'ID passwordEncoder:

<b:bean id="passwordEncoder"
    class="org.springframework.security.crypto.NoOpPasswordEncoder" factory-method="getInstance"/>

Sinon, vous pouvez préfixer tous vos mots de passe avec le bon identifiant et continuer à utiliser DelegatingPasswordEncoder. Par exemple, si vous utilisez BCrypt, vous devez migrer votre mot de passe à partir de quelque chose comme:

$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG

à

{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
7
dur

OAuth2 AuthorizationServer utilise l'authentification de base. 

Donc, vous devez également encoder votre secret client avec delegatedPasswordEncoder dans AuthorizationServerConfig pour résoudre complètement "Il n’existe aucun mot de passe PasswordEncoder mappé pour l’ID" null ". 

La réponse de Yao Liu a résolu mon problème.

1- créé un bean pour connecter automatiquement PasswordEncoder;

@Bean
public PasswordEncoder passwordEncoder() {
    String idForEncode = "bcrypt";
    Map<String, PasswordEncoder> encoderMap = new HashMap<>();
    encoderMap.put(idForEncode, new BCryptPasswordEncoder());
    return new DelegatingPasswordEncoder(idForEncode, encoderMap);
}

2- mot de passe câblé automatiqueEncoder dans la classe AuthorizationServerConfig; 

@Autowired
private PasswordEncoder passwordEncoder;

3- encodé CLIENT_SECRET avec passwordEncoder.

@Override
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
    configurer
            .inMemory()
            .withClient(CLIENT_ID)
            .secret(passwordEncoder.encode(CLIENT_SECRET))
            .authorizedGrantTypes(GRANT_TYPE_FOR_LOGIN, GRANT_TYPE_FOR_REFRESH)
            .scopes(SCOPE_READ, SCOPE_WRITE)
            .accessTokenValiditySeconds(TOKEN_VALIDITY_SECONDS)
            .refreshTokenValiditySeconds(TOKEN_VALIDITY_SECONDS)
            .resourceIds(RESOURCES_IDS);
}

C'est tout. 

3
gultekinfatih

Comme @false_memories indiqué ci-dessus, avec Spring Boot 2, vous devez coder votre secret. Dans mon projet, cela ressemble à:

public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    String secretEncoded = passwordEncoder().encode("secret");
    clients.inMemory().withClient("some-web-app").secret(secretEncoded).accessTokenValiditySeconds(expiration)
            .scopes("read", "write").authorizedGrantTypes("password", "refresh_token").resourceIds("resource");
}
1
Yao Liu

Je voulais fermer la boucle sur cette question. En plus de chiffrer les secrets du client. Le problème RedisTokenStore a également été résolu à partir de Spring OAuth 2.3.2: Spring OAuth 2.3.2

0
false_memories