Describe the bug
I'm using X509 login and trying to implement SessionCreationPolicy.ALWAYS for the /testMVCController/** endpoint and SessionCreationPolicy.STATELESS for rest of endpoints (/**).
But it looks like the stateless configured for /** applies to all endpoints, despite of @Order annotation, because I'm logging the principal authorities in UserDetailsService, and even after the first login, this list of authorities is logged at each request to the server (/testMVCController/**, .js files, .css files, ...). This means that for each request the UserDetailsService is consulted, despite of SessionCreationPolicy.ALWAYS configured for /testMVCController/** endpoints.
To Reproduce
Implement multiple HTTPSecurity configurations - one antMatcher (/testMVCController/**) and other for (/**). The /testMVCController/** should have SessionCreationPolicy.ALWAYS and /** should have SessionCreationPolicy.STATELESS.
Expected behavior
When accessing to /testMVCController/displayUsers the user logs in once through X509 client certificate and the log I have implemented in UserDetailsService logs the authorities associated to that user.
After that, all the requests to /testMVCController/displayUsers or other URL under /testMVCController/** will not go to UserDetailsService and log the authorities again because the session creation policy is always and the user is already logged in.
Sample
Could you please tell me if it is possible to achieve this behavior? I've searched this issue and I found various links (e.g. https://stackoverflow.com/questions/43523648/spring-session-creation-policy-per-request, https://stackoverflow.com/questions/63262262/spring-session-how-to-create-separate-session-management-policies-for-different and https://docs.spring.io/spring-security/site/docs/4.0.4.RELEASE/reference/html/jc.html#multiple-httpsecurity but none of them worked.
Comment From: sjohnr
@hugoalexandremf thanks for getting in touch. Using multiple security filter chains seems to be the correct way to achieve this. Unfortunately, I cannot reproduce your issue and your provided sample does not compile for me. Are you using a browser that is automatically passing the JSESSIONID up to the server on subsequent requests?
For reference, here's what I tried:
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
@Order(1)
public SecurityFilterChain customSecurityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.antMatcher("/test/**")
.authorizeRequests((authorizeRequests) -> authorizeRequests
.anyRequest().authenticated()
)
.sessionManagement(sessionManagement -> sessionManagement
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
)
.httpBasic(Customizer.withDefaults());
// @formatter:on
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.antMatcher("/**")
.authorizeRequests((authorizeRequests) -> authorizeRequests
.anyRequest().authenticated()
)
.sessionManagement(sessionManagement -> sessionManagement
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.httpBasic(Customizer.withDefaults());
// @formatter:on
return http.build();
}
@Bean
public UserDetailsService userDetailsService() {
UserDetails userDetails = User.builder()
.username("user")
.password("password")
.roles("USER")
.build();
UserDetailsService delegate = new InMemoryUserDetailsManager(userDetails);
return (username) -> {
System.out.println("In UserDetailsService");
return delegate.loadUserByUsername(username);
};
}
}
Comment From: hugoalexandremf
Thank you very much for your answer @sjohnr.
I was missing some details on my configuration. I was catching all the requests to /testMVCController/** and that was working, but in addition to catch the requests to any endpoint of the type /testMVCController/** (e.g.: /testMVCController/usersList), I also have to catch the requests that these pages make to get their scripts (.js files, .css files, .png files).
What was happening was: the request to /testMVCController/usersList), was configured with SessionCreationPolicy.ALWAYS, but the subsequent requests such as usersList.js, usersList.css, etc were configured with SessionCreationPolicy.STATELESS, and in these cases the X509CustomUserDetailsService was always consulted.
Example:
GET request to /testMVCController/usersList works, but there also requests in this usersList page to usersList.js, usersList.css, etc.
So, once I included these resource paths in the antMatchers all worked perfectly.
Once again, I apologize for opening this since it was an error on my configuration. And thank you very much for the prompt response.