web-dev-qa-db-fra.com

Spring OAuth2 - Il n'y a pas d'authentification du client. Essayez d'ajouter un filtre d'authentification approprié

Nous avons une application qui utilise spring-security-oauth2:1.0. J'essayais de le changer pour une version plus récente, spring-security-oauth2:2.0.7.RELEASE. Certaines classes ont été supprimées, certaines structures de paquetages ont été modifiées, j'ai réussi à résoudre tous ces problèmes et j'ai pu démarrer le serveur sans aucun problème. Mais je suis confronté à un problème étrange ici.

Avec OAuth2 - 1.0 version, lorsque l'utilisateur se connectait, nous avions l'habitude de faire une demande GET sur /oauth/token, par exemple:

http: // localhost: 8080/echo/oauth/token? grant_type = mot de passe & client_id = ws & client_secret = secret & scope = lire, écrire & nom d'utilisateur = john @ abc.com & mot de passe = mot123

et cela fonctionnait très bien.

Lorsque j'essaie la même chose, tout d'abord, je ne peux pas faire de requête GET en raison de la logique dans TokenEndPoint.Java

private Set<HttpMethod> allowedRequestMethods = new HashSet<HttpMethod>(Arrays.asList(HttpMethod.POST));

@RequestMapping(value = "/oauth/token", method=RequestMethod.GET)
public ResponseEntity<OAuth2AccessToken> getAccessToken(Principal principal, @RequestParam
Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
    if (!allowedRequestMethods.contains(HttpMethod.GET)) {
        throw new HttpRequestMethodNotSupportedException("GET");
    }
    return postAccessToken(principal, parameters);
}

J'ai essayé de faire une demande POST identique à l'URL ci-dessus, mais j'obtiens InsufficientAuthenticationException avec le message d'erreur

Il n'y a pas d'authentification du client. Essayez d'ajouter un filtre d'authentification approprié

Cela est dû au contrôleur de requête POST suivant dans TokenEndpoint.Java. Lorsque je débogue, je vois que principal est null.

@RequestMapping(value = "/oauth/token", method=RequestMethod.POST)
    public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
    Map<String, String> parameters) throws HttpRequestMethodNotSupportedException {
        //principal is null here
        if (!(principal instanceof Authentication)) {
            throw new InsufficientAuthenticationException(
                    "There is no client authentication. Try adding an appropriate authentication filter.");
        }
     .............
 }

J'ai un filtre d'authentification et cela a bien fonctionné lorsque j'ai utilisé version 1.0. Ce sont les prats pertinents de ma config:

    <authentication-manager xmlns="http://www.springframework.org/schema/security">
        <authentication-provider user-service-ref="userDetailsService"/>
    </authentication-manager>

   <bean id="userDetailsService" class="com.hcl.nc.service.UserDetailsService">
        <constructor-arg><ref bean="sessionFactory" /></constructor-arg>
    </bean>

J'ai toujours pensé que la demande serait authentifiée par authentication-provider et va à token-endpoint mais cela ne semble pas être le bon flux. Après avoir débogué l'application avec version 2.0.7, je doute maintenant vraiment de ma compréhension du flux.

Quelqu'un pourrait-il s'il vous plaît expliquer pourquoi cela fonctionnait dans la version précédente et pourquoi cela ne fonctionne pas maintenant?  

Dois-je faire quelque chose de différent pour obtenir un jeton OAuth?

NOTE: J'ai déjà vérifié ces questions: ici , ici , ici . Mais je n'ai pas pu trouver la bonne solution.

11
Karthik

Je ne connais pas la version précédente, mais je connais un peu la version 2.0.7.

Je soupçonne que votre problème est que votre sécurité TokenEndpoint essaie d’authentifier vos clients contre votre utilisateur service.

TokenEndpoint est protégé par un BasicAuthenticationFiltername__. Par défaut, ce filtre utiliserait une instance AuthenticationManagername__, qui contient elle-même un AuthenticationProvidername__, elle-même dépendant d'une instance de UserDetailsServicename __. L'astuce est que cette instance particulière de UserDetailsServicedoit être basée sur client, pas user based: c'est pourquoi il existe ClientDetailsUserDetailsServicename__, qui adapte ClientDetailsServiceà UserDetailsServicename__.

Normalement, tout cela est déjà fait par défaut lorsque vous utilisez les classes de configuration de la structure AuthorizationServerConfigurerAdaptername__, @EnableAuthorizationServer, etc.

5
Michael Técourt

J'ai eu le même problème et mon application.yml avait cette ligne:

servlet:
    path: /auth

l'adresse du jeton était donc: /auth/oauth/token

J'ai supprimé le chemin d'accès à application.yml, de sorte que le chemin d'accès au jeton est devenu:

/oauth/token

Et tout fonctionne bien.

J'espère cette aide

1
Paolo Mastinu

dans mon cas, j'ai trouvé cette config:

security.allowFormAuthenticationForClients (); // ici  

puis postez ce http: // localhost: 8081/sso/oauth/token? client_id = unité-client & client_secret = unité & grant_type = code_autorisation & code = Yk4Sum & redirect_uri = http: // localhost: 8082/sso-demo/passport/s'identifier

ça marche pour moi, essayez-le

@Configuration
@EnableAuthorizationServer
public class Oauth2Config extends AuthorizationServerConfigurerAdapter {

    private static final Logger log = LoggerFactory.getLogger(Oauth2Config.class);

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients(); // here 
    }

    @Override
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { // @formatter:off
        clients.inMemory()
                .withClient("unity-client")
                .secret("unity")
                .authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit", "refresh_token")
                .scopes("foo", "read", "write")
                .accessTokenValiditySeconds(3600) // 1 hour
                .refreshTokenValiditySeconds(2592000) // 30 days
        ;
    } // @formatter:on

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

}
0
mengyou

L'un des problèmes de l'erreur suivante peut être que l'authentification n'a pas été effectuée. J'ai rencontré ce problème avec une implémentation plus ancienne de Spring.

vérifier que:

TokenEndpoint -> méthode postAccessToken. Vérifiez si Principal n'est pas nul. Si elle est nulle, cela signifie que l'authentification automatique de base n'a pas été effectuée. 

Une des solutions pour ajouter un filtre était d'utiliser:

@Configuration
public class FilterChainInitializer extends AbstractSecurityWebApplicationInitializer {

}

Plus d'informations sur AbstractSecurityWebApplicationInitializer sont disponibles dans les documents Spring.

0
Damiani