In an application using Spring Security, when multiple users log in to the same account, I want to create a process that triggers an event to force everyone to log out.
For this purpose, I have implemented the following using sessionRegistry.
Configuration:
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
@Bean
public ConcurrentSessionFilter concurrentFilter() {
return new ConcurrentSessionFilter(sessionRegistry());
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.formLogin(login -> login
//other settings
).sessionManagement(session -> session
.invalidSessionUrl("/login")
.sessionConcurrency((sessionConcurrency) -> sessionConcurrency
.maximumSessions(-1)
.sessionRegistry(sessionRegistry())
)
);
return http.build();
}
Controller:
@PostMapping("/multi-logout")
@ResponseBody
public void multiLogout(@AuthenticationPrincipal UserDetailsImpl userDetails) {
String sessionId = session.getId();
Optional<Object> principal = Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
.map(authentication -> authentication.getPrincipal());
if(principal.isPresent()) {
//retrieve sessions for all users logged into the same account
List<SessionInformation> sessions = sessionRegistry.getAllSessions(principal.get(), false);
for (SessionInformation anotherSession : sessions) {
if (sessionId.equals(anotherSession.getSessionId())) {
continue;
}
anotherSession.expireNow();
}
}
}
}
I thought that if multiple users logged in to the same account, the same Principal object would be created, but this code does not retrieve all sessions because different objects would be created.
I am conducting this case on localhost and checking from different browsers. How do I destroy multiple sessions?