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:

  1. accéder à L'URI autorisé oauth pour démarrer le flux OAuth2: http://localhost:8080/server/oauth/authorize?response_type=code&client_id=client

  2. Redirection vers la page de connexion: http://localhost:8080/server/login

  3. 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

  4. 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

  5. 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" }

  6. Tentative d'accès restreint ressource utilisant access_token:http://localhost:8080/server/me?access_token=f853bcc5-7801-42d3-9cb8-303fc67b0453

  7. recevoir une réponse de token invalide

    { erreur: "invalid_token" error_description: "clé D'accès non valide: f853bcc5-7801-42d3-9cb8-303fc67b0453" }

  8. 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

  9. 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.

18
demandé sur jyore 2015-04-13 02:53:07

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.

5
répondu jyore 2015-04-14 06:53:52

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

5
répondu OhadR 2017-05-23 11:53:57

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
        }
    }
}
0
répondu fywe 2016-03-17 15:54:25