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.