web-dev-qa-db-ja.com

Spring Security OAuth2リソースサーバーが常に無効なトークンを返す

Spring Librariesを使用して実行されている基本的なインメモリOAuth2サーバーを取得しようとしています。 sparklrの例 に従っています。

現在、サーバーを構成し、ほとんどすべてが機能していますが、リソースサーバーから制限されたリソースにアクセスできません。

私のテストワークフロー:

  1. oauth許可されたURIにアクセスしてOAuth2フローを開始します。 http:// localhost:8080/server/oauth/authorize?response_type = code&client_id = client

  2. ログインページにリダイレクトします。 http:// localhost:8080/server/login

  3. 承認を処理し、設定済みのリダイレクトページにコードパラメータを付けてリダイレクトします。 http:// localhost:8080/client?code = HMJO4K

  4. クライアントIDとシークレットを付与タイプとコードとともに使用して、基本認証を使用してGETリクエストを作成します。 http:// localhost:8080/server/oauth/token?grant_type = authorization_code&code = HMJO4K

  5. Access_tokenを受け取り、代わりにトークンオブジェクトを更新する

    {access_token: "f853bcc5-7801-42d3-9cb8-303fc67b0453" token_type: "bearer" refresh_token: "57100377-dea9-4df0-adab-62e33f2a1b49" expires_in:299 scope: "read write"}

  6. Access_tokenを使用して制限されたリソースにアクセスしてみます。 http:// localhost:8080/server/me?access_token = f853bcc5-7801-42d3-9cb8-303fc67b045

  7. 無効なトークンの返信を受け取る

    {エラー: "invalid_token" error_description: "無効なアクセストークン:f853bcc5-7801-42d3-9cb8-303fc67b0453"}

  8. トークンuriに再度POSTしてトークンを更新します。 http:// localhost:8080/server/oauth/token?grant_type = refresh_token&refresh_token = 57100377-dea9-4df0-adab-62e33f2a1b49

  9. 新しいトークンを受け取る

    {access_token: "ed104994-899c-4cd9-8860-43d5689a9420" token_type: "bearer" refresh_token: "57100377-dea9-4df0-adab-62e33f2a1b49" expires_in:300 scope: "read write"}

私は何を間違っているのか本当にわかりませんが、制限されたuriにアクセスする以外のすべてが機能しているようです。私の設定は次のとおりです。

@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;
        }
    }
}

不足しているものがありますか、これに間違って近づいていますか?どんな助けも大歓迎です。

19
jyore

問題は、リソースサーバーと承認サーバーが同じトークンストア参照を取得していないことでした。配線がどのように正しく機能しなかったのかはわかりませんが、構成クラスで固定オブジェクトを使用すると、魅力のように機能しました。最終的には、永続性を備えたトークンストアに移行します。おそらく問題はありませんでした。

答えと助けをありがとう@OhadR!

最終的に、構成を単純化し、同じワークフローを実行して、うまくいきました。

@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")
            ;
        }
    }
}

この投稿に出くわした人は、完全なsparklr/tonrの例ではなく、例えば、開始するのに必ずしも必要ではない追加の設定がたくさんあるので、例えばユニットテストをもっと見ることをお勧めします。

5
jyore

手順6は間違っています-この方法では脆弱であるため、アクセストークンをURLで送信しないでください。 GETではなく、POSTを使用します。

その上、私はあなたのステップ#1を理解していません-なぜ/ oauth/authorizeを呼び出すのですか?保護されたリソースを取得しようとすると、暗黙的に実行する必要があります。つまり、フローは次のように開始する必要があります。

Access_tokenを使用して、制限されたリソースにアクセスしてみます。 http:// localhost:8080/server/me

その後、ネゴシエーションは「舞台裏」で開始されます。「/ oauth/authorize」などへのリダイレクトです。

さらに、ステップ8では、「別のアクセストークン」を要求しているのではなく、「トークンの更新」を要求していることに注意してください。アクセストークンの有効期限が切れたように。

:IDプロバイダーとリソースサーバーはtokenStoreを共有する必要があります!ここをお読みください: Spring Security OAuth2 pure resource server

HTH

5
OhadR

これは私のために働く:

@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
fywe