I'm trying to secure a Spring Boot application using Keycloak and configuring it via Java instead of XML. My SecurityConfig class looks like this:
@Configuration
@EnableWebSecurity
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class,
excludeFilters = @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.keycloak.adapters.springsecurity.management.HttpSessionManager"))
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
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.authorizeRequests()
.anyRequest().hasRole("admin");
}
}
In my understanding, the call to anyRequest should ensure that all requests are redirected to the KeyCloak login page if the user is not currently logged in. However, this only seems to work for URLs that are not the root URL. The project currently has two endpoints, "/" "/sync". Trying to access the sync-endpoint properly redirects to the login page. Trying to access the root page does not, so it seems to be ignored. I've also tried using antMatchers("*", "**", "/", "/*", "/**").hasRole("admin"), but none of those patterns seem to cause the root URL to be secured.
The culprit seems to be the call to super.configure(http). However, this executes some relatively important things, like CSRF protection, login/out endpoints etc. Here's the equivalent code extracted into the method, instead of the super-call:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(this.keycloakCsrfRequestMatcher())
.and().sessionManagement().sessionAuthenticationStrategy(this.sessionAuthenticationStrategy())
.and().addFilterBefore(this.keycloakPreAuthActionsFilter(), LogoutFilter.class)
.addFilterBefore(this.keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
.addFilterBefore(this.keycloakAuthenticatedActionsFilter(), BasicAuthenticationFilter.class)
.addFilterAfter(this.keycloakSecurityContextRequestFilter(), SecurityContextHolderAwareRequestFilter.class)
.exceptionHandling().authenticationEntryPoint(this.authenticationEntryPoint())
.and().logout().addLogoutHandler(this.keycloakLogoutHandler()).logoutUrl("/sso/logout").permitAll().logoutSuccessUrl("/");
http.authorizeRequests()
.anyRequest().hasRole("admin");
}
Reversing the order between the super-call and my own authorization code has also not resulted in ther root URL being protected.
By default logoutSuccessUrl is "/", so is unsecured, in order to secure "/" you need to change it.
.and().logout().logoutSuccessUrl("/logout-success")
I also recommend you to use keycloak-spring-boot-starter
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With