J'essaie d'obtenir un serveur OAuth2 en mémoire de base fonctionnant à l'aide des bibliothèques Spring. J'ai suivi le exemple sparklr .
J'ai actuellement configuré le serveur et presque tout fonctionne, mais je ne peux pas accéder à ma ressource restreinte depuis le serveur de ressources.
Mon workflow de test:
Accédez à l'URI autorisé oauth pour démarrer le flux OAuth2: http: // localhost: 8080/server/oauth/authorize? Response_type = code & client_id = client
Rediriger vers la page de connexion: http: // localhost: 8080/server/login
Gérer l'approbation et rediriger vers ma page de redirection configurée avec un paramètre de code: http: // localhost: 8080/client? Code = HMJO4K
Créez une demande GET à l'aide de l'authentification de base en utilisant l'ID et le secret du client ainsi que le type et le code d'autorisation: http: // localhost: 8080/server/oauth/token? Grant_type = autorisation_code & code = HMJO4K
Recevoir un access_token et actualiser un objet jeton en retour
{access_token: "f853bcc5-7801-42d3-9cb8-303fc67b0453" token_type: "bearer" refresh_token: "57100377-dea9-4df0-adab-62e33f2a1b49" expires_in: 299 scope: "read write"}
Essayez d'accéder à une ressource restreinte en utilisant le access_token: http: // localhost: 8080/server/me? Access_token = f853bcc5-7801-42d3-9cb8-303fc67b045
Recevoir une réponse de jeton non valide
{error: "invalid_token" error_description: "Jeton d'accès non valide: f853bcc5-7801-42d3-9cb8-303fc67b0453"}
POSTEZ à nouveau l'URI du jeton pour actualiser le jeton: http: // localhost: 8080/server/oauth/token? Grant_type = refresh_token & refresh_token = 57100377-dea9-4df0-adab-62e33f2a1b49
Recevez un nouveau jeton
{access_token: "ed104994-899c-4cd9-8860-43d5689a9420" token_type: "bearer" refresh_token: "57100377-dea9-4df0-adab-62e33f2a1b49" expires_in: 300 scope: "read write"}}
Je ne suis vraiment pas sûr de ce que je fais mal, mais il semble que tout autre que 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 qui me manque ou que j'aborde mal? Toute aide serait grandement appréciée.
Le problème a fini par être que le serveur de ressources et le serveur d'autorisation n'obtenaient pas la même référence de magasin de jetons. Je ne sais pas comment le câblage ne fonctionnait pas correctement, mais l'utilisation d'un objet fixe dans la classe de configuration a fonctionné comme un charme. En fin de compte, je vais passer à un magasin de jetons soutenu par la persistance, qui n'aurait probablement pas eu de problème.
Merci à @OhadR pour la réponse et l'aide!
En fin de compte, j'ai simplifié la configuration, j'ai suivi le même flux de travail et cela 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")
;
}
}
}
Quiconque tombe sur ce post, je recommande de regarder plus les tests unitaires par exemple plutôt que l'exemple complet sparklr/tonr, car il a beaucoup de configuration supplémentaire qui ne sont pas nécessairement nécessaires pour commencer.
Votre étape # 6 est incorrecte - le jeton d'accès ne doit pas être envoyé dans l'URL car il est vulnérable de cette façon. plutôt que GET, utilisez POST.
D'ailleurs, je ne comprends pas votre étape # 1 - pourquoi appelez-vous/oauth/authorize? cela doit être fait implicitement lorsque vous essayez d'obtenir une ressource protégée. Je veux dire, votre flux devrait commencer par:
Essayez d'accéder à une ressource restreinte à l'aide du jeton access_token: http: // localhost: 8080/server/me
Ensuite, la négociation commencera "dans les coulisses": une redirection vers "/ oauth/authorize" etc.
De plus, à l'étape 8, notez que vous ne demandez pas "un autre jeton d'accès", mais plutôt une demande de "rafraîchissement du jeton". Comme si votre jeton d'accès avait expiré.
Remarque : Le fournisseur d'identité et le serveur de ressources doivent partager le tokenStore! Lire ici: serveur de ressources Spring Security OAuth2 pure
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
}
}
}