I recently implemented Keycloak into my Primefaces Spring-Boot Web Application. It all works great except one thing: Ajax request "timeout" after whatever is set in keycloak under "Access Token Lifespan". There is no redirect. The ajaxStatus never ends and the user is forced to reload the page. Looking at the Request, I am getting back a 401 "Unauthorized".
E.g. the user loads a site and does whatever he wants to do. After 5 minutes of time without reloading or navigation to another page, ajax requests get unauthorized.
So my question is: What are the best practices in this situation and is this even the expected behavior?
I see following options:
- Increase the "Access Token Lifespan"
- Intercept the ajax call and reload page if user isnt authorized anymore -> user looses possible input he made on the site
- Refresh Access Token lifespan on every ajax call within its current lifespan -> Is that even possible?
Here is my SpringSecurity and Keycloak configuration:
@Configuration
@KeycloakConfiguration
@EnableWebSecurity
@EnableGlobalMethodSecurity(proxyTargetClass = true)
public class SpringSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
private KeycloakClientRequestFactory keycloakClientRequestFactory;
@Inject
public void setKeycloakClientRequestFactory(KeycloakClientRequestFactory keycloakClientRequestFactory) {
this.keycloakClientRequestFactory = keycloakClientRequestFactory;
}
@Inject
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
SimpleAuthorityMapper grantedAuthorityMapper = new SimpleAuthorityMapper();
grantedAuthorityMapper.setPrefix("ROLE_");
grantedAuthorityMapper.setConvertToUpperCase(true);
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(grantedAuthorityMapper);
auth.authenticationProvider(keycloakAuthenticationProvider);
}
@Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(
new SessionRegistryImpl());
}
@Bean
public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
KeycloakAuthenticationProcessingFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(true);
return registrationBean;
}
@Bean
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
KeycloakPreAuthActionsFilter filter) {
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(true);
return registrationBean;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/javax.faces.resource/**").permitAll()
.antMatchers("/pages/accessdenied*").permitAll()
.antMatchers("/pages/admin/**").hasRole("ADMIN")
.antMatchers("/pages/shared/**").permitAll()
.antMatchers("/pages/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.csrf().disable();
}
}
Keycloak settings
keycloak.enabled=true
keycloak.auth-server-url=http://host:8090/auth
keycloak.realm="realm"
keycloak.public-client=true
keycloak.resource="client-name"
keycloak.principal-attribute=preferred_username