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
enablesCSRF
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 theBASIC 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 needCSRF
protection, right? - even if I set
http.sessionManagement().disable()
after thesuper.configure(http)
call theJSESSIONID
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();
}
}