user3353393
user3353393

Reputation: 149

KeyCloak - Spring boot only get requests work

I have really strange problem - Im trying to enable KeyCloak from tutorial and I see its working only on get method. My configuration is ultra simple:

protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable().authorizeRequests()
        .anyRequest().hasRole("admin");
    super.configure(http);
}

I added some debug on resolver:

@Override
protected void configure(AuthenticationManagerBuilder auth) {
    KeycloakAuthenticationProvider keycloakAuthenticationProvider = new KeycloakAuthenticationProvider() {
        @Override
        public Authentication authenticate(Authentication authentication) throws AuthenticationException {
            log.debug("Auth successes.");
            final KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication;
            log.debug("User id:" + token.getAccount().getPrincipal().getName());
            log.debug("User roles:" + String.join(",", token.getAccount().getRoles()));
            return super.authenticate(authentication);
        }
    };
    keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
    auth.authenticationProvider(keycloakAuthenticationProvider);
}

And here is a problem when I put GET request to http://localhost:8080/admin/test all is fine:

DEBUG 2021-08-18 15:26:55,704 [http-nio-8080-exec-3][][] c.j.b.i.c.SecurityConfiguration 'Auth successes.'
DEBUG 2021-08-18 15:26:55,704 [http-nio-8080-exec-3][][] c.j.b.i.c.SecurityConfiguration 'User id:e53fa4a8-e7c3-46a0-9685-175fede5098e'
DEBUG 2021-08-18 15:26:55,704 [http-nio-8080-exec-3][][] c.j.b.i.c.SecurityConfiguration 'User roles:default-roles-springbootkeycloak,offline_access,admin,uma_authorization'
WARN  2021-08-18 15:26:56,093 [http-nio-8080-exec-3][][] o.a.c.util.SessionIdGeneratorBase 'Creation of SecureRandom instance for session ID generation using [SHA1PRNG] took [384] milliseconds.'
DEBUG 2021-08-18 15:26:56,102 [http-nio-8080-exec-3][50168e1c-0481-416e-a202-a24fafab58c7][] c.j.b.i.c.SecurityConfiguration 'Auth successes.'
DEBUG 2021-08-18 15:26:56,103 [http-nio-8080-exec-3][50168e1c-0481-416e-a202-a24fafab58c7][] c.j.b.i.c.SecurityConfiguration 'User id:e53fa4a8-e7c3-46a0-9685-175fede5098e'
DEBUG 2021-08-18 15:26:56,103 [http-nio-8080-exec-3][50168e1c-0481-416e-a202-a24fafab58c7][] c.j.b.i.c.SecurityConfiguration 'User roles:default-roles-springbootkeycloak,offline_access,admin,

And i got proper response without any issues but when I make exact same request for POST / DELETE / PUT I also got logs that in theory roles are fine:

DEBUG 2021-08-18 15:28:45,876 [http-nio-8080-exec-4][][] c.j.b.i.c.SecurityConfiguration 'Auth successes.'
DEBUG 2021-08-18 15:28:45,876 [http-nio-8080-exec-4][][] c.j.b.i.c.SecurityConfiguration 'User id:e53fa4a8-e7c3-46a0-9685-175fede5098e'
DEBUG 2021-08-18 15:28:45,877 [http-nio-8080-exec-4][][] c.j.b.i.c.SecurityConfiguration 'User roles:default-roles-springbootkeycloak,offline_access,admin,uma_authorization'

But as response I have:

{
    "timestamp": 1629293325879,
    "status": 403,
    "error": "Forbidden",
    "message": "Forbidden",
    "path": "/admin/test"
}

Upvotes: 1

Views: 970

Answers (1)

smotastic
smotastic

Reputation: 398

I think the problem is csrf. You are calling super.configure(http) after you disabled csrf. But in the super call (if you are using KeycloakWebSecurityConfigurerAdapter) csrf will be enabled again.

 http
   csrf().requireCsrfProtectionMatcher(keycloakCsrfRequestMatcher())
   ...

And the keycloakCsrfRequestMatcher blocks all Post and Delete Methods by default. Actually it only allows the following methods:

^(GET|HEAD|TRACE|OPTIONS)$

See https://github.com/keycloak/keycloak/blob/master/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakCsrfRequestMatcher.java

So the quick solution would be to put the super call in the beginning.

protected void configure(HttpSecurity http) throws Exception {
  super.configure(http);    
  http.csrf().disable().authorizeRequests()
        .anyRequest().hasRole("admin");
    
}

Upvotes: 2

Related Questions