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:
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.
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 BasicAuthenticationFilter
name__. Par défaut, ce filtre utiliserait une instance AuthenticationManager
name__, qui contient elle-même un AuthenticationProvider
name__, elle-même dépendant d'une instance de UserDetailsService
name __. L'astuce est que cette instance particulière de UserDetailsService
doit être basée sur client, pas user based: c'est pourquoi il existe ClientDetailsUserDetailsService
name__, qui adapte ClientDetailsService
à UserDetailsService
name__.
Normalement, tout cela est déjà fait par défaut lorsque vous utilisez les classes de configuration de la structure AuthorizationServerConfigurerAdapter
name__, @EnableAuthorizationServer
, etc.
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
dans mon cas, j'ai trouvé cette config:
security.allowFormAuthenticationForClients (); // ici
ç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 {
}
}
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.