Skip to content

Support varying maxSessions by user in Servlet #16206

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ClaudenirFreitas opened this issue Dec 2, 2024 · 7 comments · Fixed by #16218
Closed

Support varying maxSessions by user in Servlet #16206

ClaudenirFreitas opened this issue Dec 2, 2024 · 7 comments · Fixed by #16218
Assignees
Labels
in: web An issue in web modules (web, webmvc) type: enhancement A general enhancement

Comments

@ClaudenirFreitas
Copy link

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.

@ClaudenirFreitas ClaudenirFreitas added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Dec 2, 2024
@kse-music
Copy link
Contributor

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();
    }

@ClaudenirFreitas
Copy link
Author

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?

@jzheaux jzheaux changed the title Concurrent Sessions Control for Servlet Applications: configuring the maximumSessions value Support varying maxSessions by user in Servlet Dec 4, 2024
@jzheaux
Copy link
Contributor

jzheaux commented Dec 4, 2024

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?

@jzheaux jzheaux added status: ideal-for-contribution An issue that we actively are looking for someone to help us with and removed status: waiting-for-triage An issue we've not yet triaged labels Dec 4, 2024
@jzheaux jzheaux self-assigned this Dec 4, 2024
@ClaudenirFreitas
Copy link
Author

ClaudenirFreitas commented Dec 4, 2024

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.

ClaudenirFreitas pushed a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 5, 2024
@ClaudenirFreitas
Copy link
Author

ClaudenirFreitas commented Dec 5, 2024

PR has been created. Could you review it @jzheaux @kse-music ?

@jzheaux jzheaux added in: web An issue in web modules (web, webmvc) and removed status: ideal-for-contribution An issue that we actively are looking for someone to help us with labels Dec 5, 2024
ClaudenirFreitas pushed a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 6, 2024
ClaudenirFreitas pushed a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 7, 2024
@ClaudenirFreitas
Copy link
Author

ClaudenirFreitas commented Dec 7, 2024

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.

@jzheaux
Copy link
Contributor

jzheaux commented Dec 9, 2024

@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.

ClaudenirFreitas pushed a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 10, 2024
ClaudenirFreitas pushed a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 10, 2024
ClaudenirFreitas pushed a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 11, 2024
ClaudenirFreitas added a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 13, 2024
ClaudenirFreitas added a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 13, 2024
ClaudenirFreitas added a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 13, 2024
ClaudenirFreitas added a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 13, 2024
ClaudenirFreitas added a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 14, 2024
ClaudenirFreitas added a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 17, 2024
jzheaux pushed a commit to ClaudenirFreitas/spring-security that referenced this issue Dec 18, 2024
jzheaux pushed a commit that referenced this issue Dec 19, 2024
jzheaux added a commit that referenced this issue Dec 19, 2024
- Move to the web.authentication.session package since it is only needed
by web.authentication.session elements and does not access any other web
element itself.
- Add Kotlin support
- Add documentation

Issue gh-16206
kwondh5217 pushed a commit to kwondh5217/spring-security that referenced this issue Feb 4, 2025
kwondh5217 pushed a commit to kwondh5217/spring-security that referenced this issue Feb 4, 2025
- Move to the web.authentication.session package since it is only needed
by web.authentication.session elements and does not access any other web
element itself.
- Add Kotlin support
- Add documentation

Issue spring-projectsgh-16206

Signed-off-by: Daeho Kwon <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web An issue in web modules (web, webmvc) type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants