Expected Behavior
For Reactive Applications, the maximumSessions value can be configured using the SessionLimit abstraction (refer to this documentation) which also allows us to return the value based on the current authentication e.g.
@Bean
SecurityWebFilterChain filterChain(ServerHttpSecurity http) {
http
// ...
.sessionManagement((sessions) -> sessions
.concurrentSessions((concurrency) -> concurrency
.maximumSessions(maxSessions()))
);
return http.build();
}
private SessionLimit maxSessions() {
return (authentication) -> {
if (authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_UNLIMITED_SESSIONS"))) {
return Mono.empty(); // allow unlimited sessions for users with ROLE_UNLIMITED_SESSIONS
}
if (authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"))) {
return Mono.just(2); // allow two sessions for admins
}
return Mono.just(1); // allow one session for every other user
};
}
The SessionLimit abstraction was introduced by this Pull Request.
Current Behavior
For Servlet Applications, we do not have this mechanism (refer to this page). The maximumSessions is an Integer (this sample illustrate this).
Context
I have a Servlet Application running in production and cannot migrate it to a Reactive Application. I would like a similar SessionLimit abstraction for the Servlet Application. I have not found an elegant way to do it by checking the spring-security code.
I have the tenant identifier in the User Details and want to use it to retrieve the maximum session value per tenant using a service layer. This feature will be handy for the community.
I already cloned the spring-security repo and implemented a solution to support the SessionLimit abstraction for the Servlet Application.
Before creating a Pull Request, I would like your input on this.
I just closed this one because I think it is more related to this repo.
Comment From: kse-music
Maybe you can do like this
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.sessionManagement((sessions) -> {
sessions.maximumSessions(2);
sessions.addObjectPostProcessor(new ObjectPostProcessor<ConcurrentSessionControlAuthenticationStrategy>() {
@Override
public <O extends ConcurrentSessionControlAuthenticationStrategy> O postProcess(O object) {
return (O) new ConcurrentSessionControlAuthenticationStrategy(new SessionRegistryImpl()) {
@Override
protected int getMaximumSessionsForThisUser(Authentication authentication) {
if (authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_UNLIMITED_SESSIONS"))) {
return -1; // allow unlimited sessions for users with ROLE_UNLIMITED_SESSIONS
}
if (authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"))) {
return 2; // allow two sessions for admins
}
return super.getMaximumSessionsForThisUser(authentication); // allow one session for every other user
}
};
}
});
})
.build();
}
Comment From: ClaudenirFreitas
This approach makes sense when using Java classes to define the Spring Beans, but I am using the XML Schema-based configuration. Checking the docs, I have not found anything to configure addObjectPostProcessor via Spring XML files.
Additionally, I believe the framework could apply the same concept of the Session Limit strategy to both non-servlet and servlet applications. What do you think?
Comment From: jzheaux
Thanks for the suggestion, @ClaudenirFreitas. I think this is a reasonable thing to consider.
For completeness I'll mention that @kse-music's suggestion should work if you publish a BeanPostProcessor. Object post-processors are for the DSL, as you pointed out.
That said, I think it would be reasonable to add max-sessions-ref to the XML definition.
In this same ticket, we should add ConcurrencyControlSessionAuthenticationStrategy#setMaximumSessions(SessionLimit limit) and allow it to be configured in the ConcurrencyControlConfigurer
Are you able to provide a PR that adds this functionality?
Comment From: ClaudenirFreitas
Thanks for the feedback @jzheaux !
Are you able to provide a PR that adds this functionality?
Yes, of course. I will create the PR tomorrow, ok? I am working on creating the unit tests.
Comment From: ClaudenirFreitas
PR has been created. Could you review it @jzheaux @kse-music ?
Comment From: ClaudenirFreitas
PR has been created. Could you review it @jzheaux?
@jzheaux, can I recreate the PR from main to 6.1.x?
I am currently using version 6.1.5 and will not be able to upgrade to the latest version now.
Comment From: jzheaux
@ClaudenirFreitas, we typically only add features to the latest feature branch, which at the time of this writing is 6.5. In the meantime, I'd recommend the BeanPostProcessor route.