Spring Security Maximum session timeout not working

We have this

http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true)

and

http
    .logout()
    .logoutRequestMatcher(new AntPathRequestMatcher("/logout-gimli-user")).permitAll()
    .deleteCookies("JSESSIONID", "sessionid" /*, "sessdetail", "countfr"*/ );

and

 http
    .sessionManagement()
    .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
    .invalidSessionUrl("/login?invalidSession") //dokunma
    .maximumSessions(1) //dokunma
    .maxSessionsPreventsLogin(true) //dokunma
    .expiredUrl("/login?expired")
    .sessionRegistry(sessionRegistry());

in

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

And in application.properties, we have

server.servlet.session.timeout=3m

When a user tries to login, user puts password + username, then one time code is sent to user. After this, user needs to put this code and then can view pages.

But if user does not put that code but only puts usernamepassword, and closes browser, logout is not working. Because logout is not invoked.

But timeout should work and kill after 3 minutes. Or tomcat should kill the session (because we deploy to external tomcat 9).

I tried this https://stackoverflow.com/a/41450580/11369236

I added

@Bean
public static ServletListenerRegistrationBean httpSessionEventPublisher() {
    return new ServletListenerRegistrationBean(new HttpSessionEventPublisher());
}

but still same.

I put

List<SessionInformation> sessions = sessionRegistry.getAllSessions(authentication.getPrincipal(), false);

to

 @Override
public Authentication authenticate(Authentication authentication) {

in public class CustomAuthenticationProviderWithRoles implements AuthenticationProvider {

and tried lots of logins without one time code confirm and saw that, sessions are increasing.

But when i try with putting one time code, it does not allow because of maxSessionsPreventsLogin

like here:

https://github.com/spring-projects/spring-security/issues/3078

Login page code:

 <form method="POST" th:action="@{/login}">
<input autocomplete="off" class="form-control" id="mobile" name="username"
                                            type="text">
   <input autocomplete="off" class="form-control password" name="password"
                                                type="password">

                            <button class="btn btn btn-block btn-primary btn-lg"
                                            type="submit"
                                            value="Log In">LOGIN
                                    </button>

this is for login:

  http
            .formLogin()
            .loginPage("/login").permitAll()

and successhandler does this for successfull login:

         response.sendRedirect("/otp");

Then, it sets the seconds which to count from for putting code. And sends another view to put code and which contains another form and submit button.

What can be best practice? For example user can close the page after putting user name password but session still remains. Despite there are timeouts.

I can use this and it solves it but I already session timeout in application.properties:

 public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response
    request.getSession(false).setMaxInactiveInterval(11);

This Post Has One Comment

  1. No Fault

    Spring should probably allow an auto-configuration for your case above for the reactive stack as it does for servlet.

    However, “session” is state and that state won’t scale unless there is some persistent storage backing it. You can use the Spring Session abstraction with an in-memory ReactiveSessionRepository even if you don’t (yet) have a backing store like Redis or something. When you do get a proper supported backing store and add the corresponding dependencies, you can delete your in-memory ReactiveSessionRepository as spring boot will auto-configure your ReactiveSessionRepository for you.

    First, add the spring session dependency

    org.springframework.session
    spring-session-core

    Second, manually create your ReactiveSessionRepository bean. (Note: this can be auto-configured for you if you’re using Redis instead of in-memory, etc.)

    import lombok.RequiredArgsConstructor;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.boot.autoconfigure.session.SessionProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.session.ReactiveMapSessionRepository;
    import org.springframework.session.ReactiveSessionRepository;
    import org.springframework.session.config.annotation.web.server.EnableSpringWebSession;

    import java.util.concurrent.ConcurrentHashMap;

    /**
    * This ReactiveSessionRepository isn’t auto-configured so we need to create it and manually set the timeout on it.
    * Later, ReactiveRedisSessionRepository will be auto-configured so we can delete this
    */
    // https://www.baeldung.com/spring-session-reactive#in-memory-configuration
    @Configuration
    @EnableSpringWebSession
    @RequiredArgsConstructor // if lombok
    @Slf4j // if lombok
    public class SessionConfig {

    private final SessionProperties sessionProperties;

    @Bean
    public ReactiveSessionRepository reactiveSessionRepository() {
    ReactiveMapSessionRepository sessionRepository = new ReactiveMapSessionRepository(new ConcurrentHashMap());
    int defaultMaxInactiveInterval = (int) sessionProperties.getTimeout().toSeconds();
    sessionRepository.setDefaultMaxInactiveInterval(defaultMaxInactiveInterval);
    log.info(“Set in-memory session defaultMaxInactiveInterval to {} seconds.”, defaultMaxInactiveInterval);
    return sessionRepository;
    }
    }

Leave a Reply