You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Introduction
In my project we use websockets to send UI notifications. For this reason we use the SessionRegistry in order to retrieve the logged in users to send notifications to.
Everything was working well with Spring Boot 2.7.x and Spring Security 5.7.x but after the migration to Spring Boot 3 and Spring Security 6.2 I noticed that the SessionRegistry was always empty even though there were logged in users.
After struggling a lot to investigate and hard debugging, I came across the reason why this is happening.
I'm not sure if it's a bug or a wanted behavior, nevertheless I couldn't find any reference in the documentation so I'm raising here the problem.
Situation
Our application is beyond CAS authentication server. So I configured a J2eePreAuthenticatedProcessingFilter in order to catch the logged in user and manage it
I skipped the other parts of the configuration as not useful for our scenario.
When I logged in the application, the filter chain I could see in the stack was: ....->J2eePreAuthenticatedProcessingFilter.....->SessionManagementFilter...->
In the SessionManagementFilter there's the part which afterwards leads to fill the SessionRegistry by the sessionAuthenticationStrategy
as the event is caught by the SessionRegistryImpl instance. However this block of code is executed only if the session wasn't already stored in the securityContextRepository
Here is it the snippet of SessionManagementFilter where this happens (please focus on ----> comments)
----> if the securityContext is still empty, then it goes inside the if
if (!this.securityContextRepository.containsContext(request)) {
Authentication authentication = this.securityContextHolderStrategy.getContext().getAuthentication();
if (this.trustResolver.isAuthenticated(authentication)) {
// The user has been authenticated during the current request, so call the
// session strategy
try {
----> The event is raised and the SessionRegistry is filled
this.sessionAuthenticationStrategy.onAuthentication(authentication, request, response);
}
catch (SessionAuthenticationException ex) {
// The session strategy can reject the authentication
this.logger.debug("SessionAuthenticationStrategy rejected the authentication object", ex);
this.securityContextHolderStrategy.clearContext();
this.failureHandler.onAuthenticationFailure(request, response, ex);
return;
}
// Eagerly save the security context to make it available for any possible
// re-entrant requests which may occur before the current request
// completes. SEC-1396.
----> Then the context is saved
this.securityContextRepository.saveContext(this.securityContextHolderStrategy.getContext(), request,
response);
}
In Spring Security 5.7, by default the securityContextRepository for the J2eePreAuthenticatedProcessingFilter is a NullSecurityContextRepository; instead, in the SessionManagementFilter by default it's an instance of HttpSessionSecurityContextRepository.
So, in the block mentioned above, the execution goes inside the if and everything works well.
In Spring Security 6.2 we have the HttpSessionSecurityContextRepository for both the filters and because of the order in the chain, when it comes to the SessionManagementFilter, the context is already present in the securityContextRepository and it never goes inside the if, with the consequence that the event is never raised.
To Fix
In order to make it work I've just added the NullSecurityContextRepository to the J2eePreAuthenticatedProcessingFilter configuration.
@Bean
J2eePreAuthenticatedProcessingFilter j2eePreAuthenticatedProcessingFilter() {
J2eePreAuthenticatedProcessingFilter filter = new J2eePreAuthenticatedProcessingFilter();
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationDetailsSource(yestWebAuthenticationDetailsSource());
filter.setContinueFilterChainOnUnsuccessfulAuthentication(false);
filter.setSecurityContextRepository(new NullSecurityContextRepository()); ---> THE SOLUTION
return filter;
}
However I don't know if this is the correct way or just a workaround for a possible bug.
Any suggestion is very welcome
The text was updated successfully, but these errors were encountered:
Introduction
In my project we use websockets to send UI notifications. For this reason we use the SessionRegistry in order to retrieve the logged in users to send notifications to.
Everything was working well with Spring Boot 2.7.x and Spring Security 5.7.x but after the migration to Spring Boot 3 and Spring Security 6.2 I noticed that the SessionRegistry was always empty even though there were logged in users.
After struggling a lot to investigate and hard debugging, I came across the reason why this is happening.
I'm not sure if it's a bug or a wanted behavior, nevertheless I couldn't find any reference in the documentation so I'm raising here the problem.
Situation
Our application is beyond CAS authentication server. So I configured a J2eePreAuthenticatedProcessingFilter in order to catch the logged in user and manage it
I skipped the other parts of the configuration as not useful for our scenario.
When I logged in the application, the filter chain I could see in the stack was:
....->J2eePreAuthenticatedProcessingFilter.....->SessionManagementFilter...->
In the SessionManagementFilter there's the part which afterwards leads to fill the SessionRegistry by the sessionAuthenticationStrategy
this.sessionAuthenticationStrategy.onAuthentication(authentication, request, response);
as the event is caught by the SessionRegistryImpl instance. However this block of code is executed only if the session wasn't already stored in the securityContextRepository
Here is it the snippet of SessionManagementFilter where this happens (please focus on ----> comments)
In Spring Security 5.7, by default the securityContextRepository for the J2eePreAuthenticatedProcessingFilter is a NullSecurityContextRepository; instead, in the SessionManagementFilter by default it's an instance of HttpSessionSecurityContextRepository.
So, in the block mentioned above, the execution goes inside the if and everything works well.
In Spring Security 6.2 we have the HttpSessionSecurityContextRepository for both the filters and because of the order in the chain, when it comes to the SessionManagementFilter, the context is already present in the securityContextRepository and it never goes inside the if, with the consequence that the event is never raised.
To Fix
In order to make it work I've just added the NullSecurityContextRepository to the J2eePreAuthenticatedProcessingFilter configuration.
However I don't know if this is the correct way or just a workaround for a possible bug.
Any suggestion is very welcome
The text was updated successfully, but these errors were encountered: