Sessions not invalidated on password/role change or deactivation #4
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
When a user changes their password, or an admin changes a user's
systemRoleor deactivates their account, existing sessions remain valid. A compromised session stays alive indefinitely. An admin demoting someone fromadmintouserdoesn't revoke their existing admin-level session.Affected files
AuthService.java:64-83— password change does not invalidate sessionsAdminService.java:96-100— role change does not invalidate sessionsAdminService.java:102-105— deactivation does not invalidate sessionsAttack scenario
user→ their session still hasROLE_ADMINuntil it naturally expires.Recommended fix
Invalidate all sessions for the affected user on:
systemRolechangeUse Spring Session's
FindByIndexNameSessionRepositoryor maintain a session registry to look up sessions by principal.Severity
High — privilege changes and account deactivation have no immediate effect on active sessions.
👨💻 Kai — Frontend Engineer
This is a backend concern, but it surfaces meaningfully in the frontend experience — here's what I need to handle.
Frontend implications of session invalidation:
+page.server.tsload function will get a 401 (or be redirected to login). SvelteKit'shooks.server.tsshould be the place that catches this and redirects cleanly — I need to confirm that path is already handled, or add it.Questions:
Set-Cookiethat clears theJSESSIONID, or does it just invalidate server-side? The client cookie will persist until it expires or is cleared — is there a signal we can rely on to detect this on the frontend?No blockers on my end — just want to design the right post-invalidation UX flow before implementing it.
🏗️ Backend Engineer — Spring Boot / PostgreSQL Specialist
This is the right fix and it's non-trivial to implement correctly. Let me lay out the options clearly.
The core problem: Spring Security's default
InMemorySessionRepositorydoesn't support lookup by principal name. To invalidate all sessions for a given user, we need a session store that indexes by principal.Implementation options:
Spring Session with JDBC backend — store sessions in a
spring_sessiontable.FindByIndexNameSessionRepositorylets you look up all sessions byPRINCIPAL_NAME_INDEX_NAME. This is the cleanest approach and makes sessions durable across restarts. Adds a dependency (spring-session-jdbc) and requires a Flyway migration for the session tables.Spring Session with Redis — same API, faster, but adds Redis to the infrastructure. Overkill for v1 unless we already have Redis for something else.
Custom in-memory session registry — register sessions manually on login in a
ConcurrentHashMap<userId, Set<SessionId>>and invalidate programmatically. Simpler infra, but sessions are lost on restart and requires careful thread safety.My recommendation for v1: Spring Session with JDBC. It's production-appropriate, uses our existing PostgreSQL, and the
FindByIndexNameSessionRepositoryinterface is exactly what this issue calls for.Questions before implementation:
AuthService.java:64-83need to be covered.Flyway migration needed: If we go JDBC, the Spring Session schema migration needs to be added. Spring provides a standard SQL script for this — it just needs to be placed in the migrations directory with the correct version number.
🧪 QA Engineer
This is one of the harder scenarios to test because it requires multi-session state. Here's the test plan.
Unit tests:
invalidateUserSessions(userId)is called with the correct ID during password change, role change, and deactivation. UseArgumentCaptoror Mockito verify.Integration tests — this is where the real coverage lives:
Password change invalidates existing sessions:
401200Role downgrade invalidates existing session:
admintouser403(if session persists with stale role) or401(if session invalidated)Deactivation invalidates existing session:
401Current session preservation (if applicable):
If self-service password change preserves the current session, verify that only other sessions are invalidated, not the one that made the change request.
Edge cases:
Test infrastructure note: These tests require a session store that supports multi-session lookup (i.e., Spring Session JDBC or similar). The current
InMemorySessionRepositorylikely can't support these integration tests either — the infra choice and the test strategy are coupled.🔒 Sable — Security Engineer
This is one of the highest-impact issues in the backlog. Let me add precision to the threat model and fix requirements.
Why both attack scenarios are critical:
ROLE_ADMINin theSecurityContextHolder. Any role checks against the SecurityContext (not the database) will still see admin privileges until the session expires.Fix requirements from a security perspective:
Authenticationobject, re-login must re-fetch them.admin_audit_logwith: admin who performed the action, affected user, reason (password change / role change / deactivation), timestamp.Session fixation note: While implementing session management changes, confirm that
sessionFixation().migrateSession()(or.newSession()) is configured inSecurityFilterChain. Session fixation protection is a related concern that should be audited alongside this fix.Question: What is the current session expiration configured to? If it's very short (e.g., 15 minutes), the urgency of this fix is slightly lower. If it's hours or persistent ("remember me"), this is urgent. Either way the fix is correct — just affects prioritization.
🎨 Atlas — UI/UX Designer
The security fix is clear, but the UX around it needs deliberate design — especially the moments where a user discovers their session has been terminated without warning.
UX scenarios I want to design for:
Self-service password change → session invalidated → redirect to login:
The user should see a clear, non-alarming message: "Password changed successfully. Please log in with your new password." This is expected behavior — just needs the right framing so it doesn't feel like an error.
Account deactivated while browsing → next request fails:
The user hits a page, gets bounced to login. They try to log in and get an error. What does that error say? "Your account has been deactivated. Contact your administrator." — clear and actionable, not a generic auth failure.
Role downgraded while browsing → session invalidated → redirect to login:
Similar pattern. The message could be neutral: "Your session has ended. Please log in again." No need to expose that their role was changed — that's an admin action they'll find out about through normal interaction.
Design questions: