'SecurityContextHolder.getContext().getAuthentication() not anonymous, but request.getHeader("Authorization") missing
We are implementing a role-based security API (bearer-token only) with spring-boot and Keycloak.
The security config looks as follows:
@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
/**
* Registers the KeycloakAuthenticationProvider with the authentication manager.
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
@Bean
public KeycloakConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
/**
* Defines the session authentication strategy.
* For bearer-only applications there is no session needed and therefor
* we use the NullAuthenticatedSessionStrategy.
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
super.configure(http);
http.authorizeRequests()
.anyRequest()
.permitAll();
}
}
I retrieve roles with
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth instanceof KeycloakAuthenticationToken) {
SimpleKeycloakAccount user = (SimpleKeycloakAccount) auth.getDetails();
for (String role : user.getRoles()) {
// Clean and collect roles...
}
}
This works and we get the roles. The problem is, that we even get roles when no request header "Authorization: Bearer [token]" has been send. This happens, when we have two consecutive calls, the first with valid token, then the second call (without Authorization header) has the same KeycloakAuthenticationToken with the same roles.
My questions are now:
- How can it be that the Authorization header is null, but the security context still returns a
KeycloakAuthenticationToken? - Shouldn't the security context be per thread, and each thread exists during a single http request only?
Update I found a workaround in the meantime, that is ugly but solves the problem for the moment. I've written a custom HandlerInterceptor, that cleans the security context, if no Authorization header can be found:
if (request.getHeader("Authorization") == null)
SecurityContextHolder.clearContext();
Although this seems to solve the issue, it shouldn't be necessary. So something is still strange, I guess.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
