Published 14 Oct, 2022

Java - Why Keycloak in Spring Boot allow an (expected unauthorized) user?

Category Java
Modified : Nov 28, 2022
10

I'm trying to using Keycloak with Spring Boot and I configured Keycloak with two user: user1 with a role "user" and user2 with a role "not-user".

I expect that when I call the endpoints with user1 everything is fine, while when I call them with user2 the access is denied... but it doesn't happen!!!

Even with user2 I can make calls!


This is the log when I make a single call with user2:

2020-05-21 10:32:22.483 DEBUG 30380 --- [nio-7771-exec-5] o.k.adapters.PreAuthActionsHandler       : adminRequest http://localhost:7771/contexts/LOCAL/files/upload
2020-05-21 10:32:22.485 DEBUG 30380 --- [nio-7771-exec-5] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /contexts/LOCAL/files/upload
2020-05-21 10:32:22.485 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.AuthenticatedActionsHandler        : AuthenticatedActionsValve.invoke http://localhost:7771/contexts/LOCAL/files/upload
2020-05-21 10:32:22.486 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.AuthenticatedActionsHandler        : Policy enforcement is disabled.
2020-05-21 10:32:22.486 DEBUG 30380 --- [nio-7771-exec-5] o.k.adapters.PreAuthActionsHandler       : adminRequest http://localhost:7771/contexts/LOCAL/files/upload
2020-05-21 10:32:22.487 DEBUG 30380 --- [nio-7771-exec-5] f.KeycloakAuthenticationProcessingFilter : Request is to process authentication
2020-05-21 10:32:22.487 DEBUG 30380 --- [nio-7771-exec-5] f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
2020-05-21 10:32:22.487 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.BearerTokenRequestAuthenticator    : Found [1] values in authorization header, selecting the first value for Bearer.
2020-05-21 10:32:22.488 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.BearerTokenRequestAuthenticator    : Verifying access_token
2020-05-21 10:32:22.493 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.BearerTokenRequestAuthenticator    : successful authorized
2020-05-21 10:32:22.493 DEBUG 30380 --- [nio-7771-exec-5] a.s.a.SpringSecurityRequestAuthenticator : Completing bearer authentication. Bearer roles: [not-user] 
2020-05-21 10:32:22.493 DEBUG 30380 --- [nio-7771-exec-5] o.k.adapters.RequestAuthenticator        : User 'user2' invoking 'http://localhost:7771/contexts/LOCAL/files/upload' on client 'fs-app'
2020-05-21 10:32:22.494 DEBUG 30380 --- [nio-7771-exec-5] o.k.adapters.RequestAuthenticator        : Bearer AUTHENTICATED
2020-05-21 10:32:22.494 DEBUG 30380 --- [nio-7771-exec-5] f.KeycloakAuthenticationProcessingFilter : Auth outcome: AUTHENTICATED
2020-05-21 10:32:22.494 DEBUG 30380 --- [nio-7771-exec-5] f.KeycloakAuthenticationProcessingFilter : Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.key[email protected]8e43f478: Principal: user2; Credentials: [PROTECTED]; Authenticated: true; Details: org[email protected]6489f7f5; Granted Authorities: ROLE_not-user
2020-05-21 10:32:22.494 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.AuthenticatedActionsHandler        : AuthenticatedActionsValve.invoke http://localhost:7771/contexts/LOCAL/files/upload
2020-05-21 10:32:22.494 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.AuthenticatedActionsHandler        : Policy enforcement is disabled.
2020-05-21 10:32:22.495 DEBUG 30380 --- [nio-7771-exec-5] f.KeycloakAuthenticationProcessingFilter : Request is to process authentication
2020-05-21 10:32:22.495 DEBUG 30380 --- [nio-7771-exec-5] f.KeycloakAuthenticationProcessingFilter : Attempting Keycloak authentication
2020-05-21 10:32:22.496 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.BearerTokenRequestAuthenticator    : Found [1] values in authorization header, selecting the first value for Bearer.
2020-05-21 10:32:22.496 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.BearerTokenRequestAuthenticator    : Verifying access_token
2020-05-21 10:32:22.500 DEBUG 30380 --- [nio-7771-exec-5] o.k.a.BearerTokenRequestAuthenticator    : successful authorized
2020-05-21 10:32:22.501 DEBUG 30380 --- [nio-7771-exec-5] a.s.a.SpringSecurityRequestAuthenticator : Completing bearer authentication. Bearer roles: [not-user] 
2020-05-21 10:32:22.501 DEBUG 30380 --- [nio-7771-exec-5] o.k.adapters.RequestAuthenticator        : User 'user2' invoking 'http://localhost:7771/contexts/LOCAL/files/upload' on client 'fs-app'
2020-05-21 10:32:22.501 DEBUG 30380 --- [nio-7771-exec-5] o.k.adapters.RequestAuthenticator        : Bearer AUTHENTICATED
2020-05-21 10:32:22.501 DEBUG 30380 --- [nio-7771-exec-5] f.KeycloakAuthenticationProcessingFilter : Auth outcome: AUTHENTICATED
2020-05-21 10:32:22.502 DEBUG 30380 --- [nio-7771-exec-5] f.KeycloakAuthenticationProcessingFilter : Authentication success using bearer token/basic authentication. Updating SecurityContextHolder to contain: org.key[email protected]c999a381: Principal: user2; Credentials: [PROTECTED]; Authenticated: true; Details: org[email protected]55a7758e; Granted Authorities: ROLE_not-user
2020-05-21 10:32:22.502 DEBUG 30380 --- [nio-7771-exec-5] o.k.adapters.PreAuthActionsHandler       : adminRequest http://localhost:7771/contexts/LOCAL/files/upload
2020-05-21 10:32:22.533  INFO 30380 --- [nio-7771-exec-5] c.s.s.f.c.FileStorageController          : POST request on /contexts//files/upload

In my build.gradle I've included the dependencies:

compile group: 'org.keycloak', name: 'keycloak-spring-boot-starter', version: '10.0.1'
compile group: 'org.keycloak', name: 'keycloak-spring-security-adapter', version: '10.0.1'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.security:spring-security-test'

The proerties for Keycloak are:

keycloak.auth-server-url=http://localhost:8180/auth
keycloak.realm=SpringBootKeycloak
keycloak.resource=fs-app
#keycloak.use-resource-role-mappings=true
keycloak.public-client=true
keycloak.principal-attribute=preferred_username

The Keycloak configuration class is:

@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

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

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(
                new SessionRegistryImpl());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http
                .csrf().disable()

                .authorizeRequests()
                .antMatchers("/*")
                .hasRole("user")
                .anyRequest()
                .permitAll();
    }
}

What am I missing? Any particular configuration to do for Keycloak?


EDIT: This is a similar problem, but in my case my SecurityConfig class isn't ignored!

Answers

There are 2 suggested solutions here and each one has been listed below with a detailed description. The following topics have been covered briefly such as Java, Keycloak, Spring Boot. These have been categorized in sections for a clear and precise explanation.

26

It was an asterisk!!!

In SecurityConfig class using .antMatchers("/**") instead of .antMatchers("/*") resolved the issue!


28

You're using the Spring Boot adapter and that's not the way to secure your web content. You should instead do it by using the Spring Boot configuration:

keycloak.securityConstraints[1].authRoles[0] = user
keycloak.securityConstraints[1].securityCollections[0].patterns[0] = /*

If you want to use Spring Security which provides much more flexibility, use the Spring Security adapter instead (yes, you can use it even with Spring Boot altogether).