Max session doesn't work when I set it in Spring Security

30 views Asked by At

I am trying to secure my application with Spring security and spring session but setting max_session as 1 doesn't work.

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    private final UserDetailsSecurityService userDetailsSecurityService;

    @Autowired
    public SecurityConfig(UserDetailsSecurityService userDetailsSecurityService, JdbcIndexedSessionRepository jdbcIndexedSessionRepository, ObjectMapper objectMapper) {
        this.userDetailsSecurityService = userDetailsSecurityService;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return Pbkdf2PasswordEncoder.defaultsForSpringSecurity_v5_8();
    }

    @Bean
    protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .authorizeHttpRequests(this::authorizeHttpRequest)
                .sessionManagement(this::sessionManagement)
                .authenticationManager(authenticationManager())
                .securityContext((securityContext) -> securityContext.securityContextRepository(securityContextRepository()))
                .csrf(AbstractHttpConfigurer::disable)
                .cors(AbstractHttpConfigurer::disable);

        return httpSecurity.build();
    }

    @Bean
    public SecurityContextRepository securityContextRepository() {
        return new HttpSessionSecurityContextRepository();
    }

    @Bean
    public SessionRegistryImpl sessionRegistry() {
        return new SessionRegistryImpl();
    }

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

    @Bean
    public SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
    }

    private void sessionManagement(SessionManagementConfigurer<HttpSecurity> session) {
        session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .maximumSessions(1) 
                .maxSessionsPreventsLogin(true)
                .sessionRegistry(sessionRegistry());
        session.sessionFixation().newSession();
        session.sessionAuthenticationStrategy(sessionAuthenticationStrategy());
    }

    private void authorizeHttpRequest(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry requests) {
        // some authorizations
    }

    @Bean
    public AuthenticationManager authenticationManager() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(userDetailsSecurityService);
        authenticationProvider.setPasswordEncoder(passwordEncoder());

        ProviderManager providerManager = new ProviderManager(Collections.singletonList(authenticationProvider));
        providerManager.setEraseCredentialsAfterAuthentication(false);

        return providerManager;
    }

}

here is my login code;

public void login(UserLoginDTO loginDTO, HttpServletRequest request, HttpServletResponse response) {
    try {
        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginDTO.email(), loginDTO.password()));
        SecurityContext securityContext = SecurityContextHolder.getContext();
        securityContext.setAuthentication(authentication);
        securityContextRepository.saveContext(securityContext, request, response);
        sessionRegistry.registerNewSession(request.getSession().getId(), authentication.getPrincipal());
    } catch (BadCredentialsException e) {
        log.warn("login attempt with wrong credentials from: " + loginDTO.email());
        throw new RuntimeException("Wrong Credentials");
    }
}

I use jdbc as session storage.

I can login second time if maxSessionsPreventsLogin(true) and I can see more than one record with same principle if maxSessionsPreventsLogin(true).

What should I change/edit to make sure only one active session exists. I know I can handle this myself but I want spring to handle this.

Thanks for any help and suggestion.

0

There are 0 answers