Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Keycloak Adapter (Spring-Security & Spring Boot) session requirement

For a software in active development we are using Spring Boot (with Spring Security) and the Keycloak Adapter.

The goal is to:

  • require valid authentication for all endpoints except those annotated with @Public (see the code snippet) (this works)
  • the authentication must be via OAuth - the client gets a token directly from Keycloak and the Spring Security + Keycloak adapter make sure it is valid
  • optionally, Basic Auth is also supported (the Keycloak adapter can be configured to perform a login and make it appear like a regular token auth for the rest of the code) (this works as well)

Everything is working fine as it stands, but I have some problems understanding a few details:

  • The KeycloakWebSecurityConfigurerAdapter enables CSRF protection. I think this is only done so it can register its own Matcher to allow requests from Keycloak
  • It enables session management and requires some according beans
  • Even though requests are made with token authentication, a JSESSIONID cookie is returned

According to my understanding:

  • sessions should not be needed since stateless token authentication is used (so why is the KeycloakWebSecurityConfigurerAdapter enabling it). Is this only for the BASIC Auth part?
  • since sessions are enabled, CSRF protection is indeed needed - but I don't want the sessions in the first place and then the API would not need CSRF protection, right?
  • even if I set http.sessionManagement().disable() after the super.configure(http) call the JSESSIONID cookie is set (so where is this coming from?)

As stated in the code snippet, SessionAuthenticationStrategy is not set to the null once since we use the Authorization part of Keycloak and the application is a Service Account Manager (thus managing those resource records).

Would be great if someone can clear things up. Thanks in advance!

@KeycloakConfiguration
public class WebSecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {

    @Inject private RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Override
    protected void configure(final HttpSecurity http) throws Exception {
        super.configure(http);
        http
            .authorizeRequests()
                .requestMatchers(new PublicHandlerMethodMatcher(requestMappingHandlerMapping))
                    .permitAll()
                .anyRequest()
                    .authenticated();
    }

    // ~~~~~~~~~~ Keycloak ~~~~~~~~~~

    @Override
    @ConditionalOnMissingBean(HttpSessionManager.class)
    @Bean protected HttpSessionManager httpSessionManager() {
        return new HttpSessionManager();
    }

    /**
     * {@link NullAuthenticatedSessionStrategy} is not used since we initiate logins
     * from our application and this would not be possible with {@code bearer-only}
     * clients (for which the null strategy is recommended). 
     */
    @Override
    @Bean protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    /**
     * HTTP session {@link ApplicationEvent} publisher needed for the
     * {@link SessionRegistryImpl} of {@link #sessionAuthenticationStrategy()}
     * to work properly.
     */
    @Bean public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }

    @Override
    @Bean public KeycloakAuthenticationProvider keycloakAuthenticationProvider() {
        return super.keycloakAuthenticationProvider();
    }

}
like image 202
AskingTheGoodQuestions Avatar asked Jul 11 '19 09:07

AskingTheGoodQuestions


1 Answers

You may fall into excessive JWT token usage. Look at this article for example https://blog.logrocket.com/jwt-authentication-best-practices/. Especially look at the references at the end of the article about JWT as a session token.

For your web-application UI you are using sessions in most of the cases. It doesn't matter what type of token is used for authentication. Keycloak does everything correctly - it gives back httpOnly secure cookie for session management and tracks user status at backend. For better understanding of how it works you may look at the example code here: examples

For better separation of stateless backend (micro-)services and user UI session keycloak documentation suggest to use 2 different authentication stratagies: RegisterSessionAuthenticationStrategy for sessions and NullAuthenticatedSessionStrategy for bearer-only services

like image 185
Vadim Avatar answered Sep 26 '22 03:09

Vadim