web-dev-qa-db-ja.com

スプリングブート(セキュリティ)とキークロークでロール認証を有効にしますか?

簡単なことをしようとしています。

単一のエンドポイントにリクエストを送信し、(クライアントから)ベアラートークンを送信したいのですが、このトークンを検証し、エンドポイントのキークロークの受け入れ/拒否リクエストに割り当てられたロールに応じて検証します。

私は多くのチュートリアルと本さえ追いかけましたが、それらすべてのほとんどは私は単に理解していません。

これに従って、キークローク情報(レルム、ロール、ユーザー)をセットアップしました https://medium.com/@bcarunmail/securing-rest-api-using-keycloak-and-spring-oauth2-6ddf3a1efcc2

そう、

私は基本的に、クライアント、特定の役割「ユーザー」を持つユーザーでキークロークを設定し、次のように構成しました。

@Configuration
@KeycloakConfiguration
//@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
public class SecurityConf extends KeycloakWebSecurityConfigurerAdapter
{
    /**
     * Registers the KeycloakAuthenticationProvider with the authentication manager.
     */
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(keycloakAuthenticationProvider());
    }

    /**
     * Defines the session authentication strategy.
     */
    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }

    @Bean
    public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
            KeycloakAuthenticationProcessingFilter filter) {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
            KeycloakPreAuthActionsFilter filter) {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
        registrationBean.setEnabled(false);
        return registrationBean;
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception
    {
        super.configure(http);
        http
                .authorizeRequests()
                .antMatchers("/user/*").hasRole("admin")
                .antMatchers("/admin*").hasRole("user")

    }
}

多くのチュートリアルでこれが(最後のルールとして)表示される理由がわかりません。

.anyRequest().permitAll();

基本的に、セキュリティがないと設定すると、無記名トークンなしでエンドポイントを呼び出すことができます。

しかし、これを最後のルールとして追加すると

 .anyRequest().denyAll();

私はいつも403を受け取ります。

私はこれを見つけたデバッグ:

リクエストは認証を処理することです

f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
o.k.a.BearerTokenRequestAuthenticator    : Found [1] values in authorization header, selecting the first value for Bearer.
o.k.a.BearerTokenRequestAuthenticator    : Verifying access_token
o.k.a.BearerTokenRequestAuthenticator    : successful authorized
a.s.a.SpringSecurityRequestAuthenticator : Completing bearer authentication. Bearer roles: [] 
o.k.adapters.RequestAuthenticator        : User 'testuser' invoking 'http://localhost:9090/api/user/123' on client 'users'
o.k.adapters.RequestAuthenticator        : Bearer AUTHENTICATED
f.KeycloakAuthenticationProcessingFilter : Auth outcome: AUTHENTICATED
o.s.s.authentication.ProviderManager     : Authentication attempt using org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider
o.s.s.core.session.SessionRegistryImpl   : Registering session 5B871A0E2AF55B70DC8E3B7436D79333, for principal testuser
f.KeycloakAuthenticationProcessingFilter : Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken@355f68d6: Principal: testuser; Credentials: [PROTECTED]; Authenticated: true; Details: org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount@5d7a32a9; Not granted any authorities
[nio-9090-exec-3] o.s.security.web.FilterChainProxy        : /api/user/123 at position 8 of 15 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
nio-9090-exec-3] o.s.s.w.s.DefaultSavedRequest            : pathInfo: both null (property equals)
[nio-9090-exec-3] o.s.s.w.s.DefaultSavedRequest            : queryString: both null (property equals)

私は無記名の役割を取得していないようです...

私の依存関係:

        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-starter</artifactId>
            <version>6.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-security-adapter</artifactId>
            <version>6.0.1</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

私の問題?

アクセストークンの送信をリクエストします。

client_id -> my client from keycloak
username -> my user from keycloak
password -> my password from keycloak
grant_type -> password
client_secret -> from keycloak

トークンを取得し、アプリのエンドポイントにリクエストするために使用します。 私のエンドポイント(役割ユーザーまたは役割管理者のエンドポイント)に関係なく、私の要求は常に有効です

私のプロパティで私はこのようなものを持っています:

keycloak:
  auth-server-url: http://localhost:8080/auth/
  resource: users-api
  credentials:
    secret : my-secret
  use-resource-role-mappings : true
  realm: my-realm
  realmKey:  my-key
  public-client: true
  principal-attribute: preferred_username
  bearer-only: true

この場合、実際に役割を有効にする方法はありますか?

JWTを使用するようにクライアントを構成する必要がありますか?何か案は?

エンドポイントにも注釈を追加しました

@Secured("admin")
@PreAuthorize("hasAnyAuthority('admin')")

彼らは何もしないようです...

-編集-

リソースに一致するようにURLを修正した後も、403を取得します。

"realm_access": {
    "roles": [
      "offline_access",
      "admin",
      "uma_authorization"
    ]
  },
  "resource_access": {
    "account": {
      "roles": [
        "manage-account",
        "manage-account-links",
        "view-profile"
      ]
    }
  },

それはどういうわけかresource_accessを私の問題に関連付けていますか?

13
jpganz18
  1. @Configurationなしで試しますか? SecurityConfクラスには@KeycloakConfigurationアノテーションのみが必要だと思います。

  2. AntMatchersは大文字と小文字の区別を尊重しますか?

 http
    .csrf().disable()
    .authorizeRequests()
    .antMatchers("/api/user/**").hasRole("user")
    .antMatchers("/api/admin/**").hasRole("admin")
    .anyRequest().authenticated();
  1. Javaで定義されているROLE_ *規則を削除するには、この構成も試してください。
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        // SimpleAuthorityMapper is used to remove the ROLE_* conventions defined by Java so
        // we can use only admin or user instead of ROLE_ADMIN and ROLE_USER
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }
  1. すべてのエンドポイントが同じロジックを持つ場合、セキュリティ構成で十分であり、他のアノテーションは必要ありません。ただし、「/ api/admin」コントローラーにない、adminの役割を持つ別のエンドポイントがある場合は、以下を試すことができます。
@PreAuthorize("hasRole('admin')")
0
bamandine