Spring Security OAuth2 Resource Server Toujours En Retournant Un Token Non Valide
j'essaie d'obtenir un serveur de base en mémoire OAuth2 tournant en utilisant les bibliothèques de printemps. J'ai été à la suite de la sparklr exemple.
j'ai configuré le serveur et presque tout fonctionne, mais je ne peux pas accéder à ma ressource restreinte à partir du serveur de ressources.
mon workflow de test:
accéder à L'URI autorisé oauth pour démarrer le flux OAuth2: http://localhost:8080/server/oauth/authorize?response_type=code&client_id=client
Redirection vers la page de connexion: http://localhost:8080/server/login
Gérer l'approbation et la redirection vers ma page de redirection configurée avec le paramètre de code:http://localhost:8080/client?code=HMJO4K
construire une requête GET en utilisant L'Auth de base en utilisant l'id du client et le secret avec le type de subvention et le code: http://localhost:8080/server/oauth/token?grant_type=authorization_code&code=HMJO4K
recevoir un objet access_token et refresh token en retour
{ access_token: "f853bcc5-7801-42d3 - 9cb8-303fc67b0453" token_type: "au porteur" "57100377-dea9-4df0-Adab-62e33f2a1b49" expires_in: 299 champ d'application: "en lecture et en écriture" }
Tentative d'accès restreint ressource utilisant access_token:http://localhost:8080/server/me?access_token=f853bcc5-7801-42d3-9cb8-303fc67b0453
recevoir une réponse de token invalide
{ erreur: "invalid_token" error_description: "clé D'accès non valide: f853bcc5-7801-42d3-9cb8-303fc67b0453" }
POSTE le jeton uri de nouveau pour rafraîchir jeton: http://localhost:8080/server/oauth/token?grant_type=refresh_token&refresh_token=57100377-dea9-4df0-adab-62e33f2a1b49
Recevoir un nouveau jeton
{ access_token: "ed104994-899c - 4cd9-8860-43d5689a9420" token_type: "au porteur" "57100377-dea9-4df0-Adab-62e33f2a1b49" expires_in: 300 champ d'application: "en lecture et en écriture" }
Je ne suis vraiment pas sûr de ce que je fais mal, mais il semble que tout sauf l'accès à l'uri restreint fonctionne. Voici ma configuration:
@Configuration
public class Oauth2ServerConfiguration {
private static final String SERVER_RESOURCE_ID = "oauth2-server";
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(SERVER_RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and().requestMatchers()
.antMatchers("/me")
.and().authorizeRequests()
.antMatchers("/me").access("#oauth2.clientHasRole('ROLE_CLIENT')")
;
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthotizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.resourceIds(SERVER_RESOURCE_ID)
.secret("secret")
.authorizedGrantTypes("authorization_code", "refresh_token")
.authorities("ROLE_CLIENT")
.scopes("read","write")
.redirectUris("http://localhost:8080/client")
.accessTokenValiditySeconds(300)
.autoApprove(true)
;
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore())
.userApprovalHandler(userApprovalHandler())
.authenticationManager(authenticationManager)
;
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.realm("oauth");
}
@Bean
public ApprovalStore approvalStore() throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore());
return store;
}
@Bean
public UserApprovalHandler userApprovalHandler() throws Exception {
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
handler.setTokenStore(tokenStore());
return handler;
}
}
}
y a-t-il quelque chose que je manque ou est-ce que j'approche mal? Toute aide serait grandement appréciée.
3 réponses
Le problème a fini par être que le serveur de ressources et le serveur d'autorisation n'étaient pas obtenir le même magasin de référence. Je ne suis pas sûr que le câblage ne fonctionne pas correctement, mais utiliser un objet fixe dans la classe de configuration a fonctionné comme un charme. En fin de compte, je vais passer à un magasin de tokens adossé à la persistance, qui n'aurait probablement pas eu de problèmes.
merci à @OhadR pour la réponse et l'aide!
finalement, j'ai simplifié le configuration, suis passé par le même flux de travail, et ça a fonctionné
@Configuration
public class Oauth2ServerConfiguration {
private static final String SERVER_RESOURCE_ID = "oauth2-server";
private static InMemoryTokenStore tokenStore = new InMemoryTokenStore();
@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/me").and().authorizeRequests().antMatchers("/me").access("#oauth2.hasScope('read')");
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.authorizedGrantTypes("authorization_code","refresh_token")
.authorities("ROLE_CLIENT")
.scopes("read")
.resourceIds(SERVER_RESOURCE_ID)
.secret("secret")
;
}
}
}
quelqu'un qui tombe sur ce post, je vous recommande de regarder plus les tests unitaires pour l'exemple, plutôt que de la pleine soufflé sparklr/tonr exemple, comme il a beaucoup de configuration supplémentaires qui ne sont pas forcément nécessaires pour commencer.
votre étape #6 est erronée - le token d'accès ne doit pas être envoyé dans L'URL car il est vulnérable de cette façon. rathen than GET, utilisez POST.
d'Ailleurs, je ne comprends pas votre étape #1 - pourquoi l'appelez-vous /oauth/autoriser? cela devrait être fait implicitement lorsque vous essayez d'obtenir une ressource protégée. Je veux dire, votre flux devrait commencer par:
tentative d'accéder à une ressource restreinte en utilisant le logiciel access_token: http://localhost:8080/server/me
alors la négociation commencera "behind the scenes": une redirection vers "/oauth / authorize" etc.
de plus, à l'étape #8, notez que vous ne demandez pas "un autre token d'accès", mais plutôt une requête pour "rafraîchir le token". Comme si votre accès-token était expiré.
Remarque:: Le fournisseur d'identité et le serveur de ressources doivent partager la tokenStore! Lire ici: Printemps Sécurité OAuth2 pure serveur de ressources
HTH
Cela fonctionne pour moi:
@Configuration
public class Oauth2ServerConfiguration {
private static final String SERVER_RESOURCE_ID = "oauth2-server";
@Autowired
private TokenStore tokenStore;
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Configuration
@EnableResourceServer
protected static class ResourceServer extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(tokenStore).resourceId(SERVER_RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
// ... Not important at this stage
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore).approvalStoreDisabled();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//... Not important at this stage
}
}
}