Signup creates session but never authenticates the user #3
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
In
AuthController.signup(), a session is created viahttpRequest.getSession(true)but the user is never authenticated into the Spring SecurityContext. The session cookie is issued but has no associated authentication, which is confusing and potentially exploitable.Affected files
AuthController.java:28-29Recommended fix
Either:
SecurityContextHolder.getContext().setAuthentication(...)) if auto-login after signup is desired, orgetSession(true)call entirely if signup should not create a session.Severity
Critical — orphaned sessions can cause session confusion and bypass session-fixation protection.
👨💻 Kai — Frontend Engineer
This bug directly affects the signup → auto-login → redirect flow that the frontend depends on. I need clarity on the intended post-signup behavior before I can implement the correct frontend handling.
Current frontend assumption:
The frontend likely does one of two things after a successful signup POST:
/plan)If option 1 is intended but the session is never authenticated (which is the bug), the redirect to
/planwill immediately 401 back to login, creating a confusing loop.Questions for the team:
+page.server.tssignup action should then redirect to/plan(or onboarding). Confirm the redirect target.getSession(true)call should just be removed. My signup action redirects to/login?signup=successand the login page shows a confirmation banner.What I'll handle regardless:
+page.server.tssignup action needs to handle both 201 (success) and any error responses cleanlyhooks.server.tsneeds to correctly detect an unauthenticated session (the orphaned session from this bug) and treat it as "not logged in"No code changes from me until the backend fix approach is decided — the correct frontend flow depends entirely on which fix path is chosen.
🏗️ Backend Engineer — Spring Boot / PostgreSQL Specialist
Marked Critical — correctly. The orphaned session is the dangerous part. Let me lay out the two fix paths precisely.
Fix path A: Auto-login after signup (authenticate into SecurityContext)
This is the correct implementation if auto-login is desired. The session is created AND tied to a real
Authenticationobject.Fix path B: No session at signup (remove
getSession(true))Just remove the
httpRequest.getSession(true)call. Signup returns the user resource, no session created. Frontend redirects to login.My strong recommendation: Fix path A (auto-login) — it's the better UX and the more secure option because:
Questions:
ROLE_USER? Or is there aUserDetailsServicelookup we should go through to load the fullUserDetails?authService.signup()return enough information to build theAuthenticationobject (email, roles), or does it need to do a follow-uploadUserByUsernamecall?authService.signup()transactional? The session should only be created if the DB write succeeds — want to confirm the failure path doesn't leave a session behind.🧪 QA Engineer
Critical severity means I want this covered with both unit and integration tests before the fix ships. Here's the full test plan.
Current behavior to confirm (regression baseline):
401(proving the session has no auth). This documents the bug and becomes the test that must fail before the fix and pass after.Fix path A tests (auto-login after signup):
POST /v1/auth/signupwith valid data →201, response contains user info,Set-CookiewithJSESSIONIDGET /v1/auth/me(or any authenticated endpoint) →200(not401) — this is the key test proving the session is authenticated409, no session created400/422, no session createdFix path B tests (no session at signup):
POST /v1/auth/signup→201, noSet-Cookieheader (or cookie cleared)Edge cases for either fix:
authService.signup()throws mid-execution? Is any partial session state left behind?E2E coverage: The signup → dashboard flow should be a critical E2E test tagged
@critical. It's the first thing a new user does — if it's broken, nothing else matters.🔒 Sable — Security Engineer
This is correctly rated Critical. The orphaned session is the most dangerous part — let me explain the attack surface clearly.
The orphaned session attack vector:
httpRequest.getSession(true)creates a real HTTP session with aJSESSIONIDcookie. The session exists in the session store but has noAuthenticationin itsSecurityContext. This means:Session fixation risk: If an attacker can predict or influence the session ID before signup (e.g., by pre-visiting the site and getting a session cookie, then injecting it into the signup request), they could potentially fix the session ID. Spring's session fixation protection (
migrateSession()) is supposed to fire on authentication — but since authentication never happens here, that protection never runs. The session is created but fixation protection is bypassed.Session confusion: The orphaned session persists until expiration. If another code path incorrectly treats "session exists" as "user is authenticated," the unauthenticated session could be misused.
Resource exhaustion: If signup is called at scale (even legitimately), orphaned sessions accumulate in the session store until they expire. Combined with the lack of rate limiting on
/v1/auth/signup(see issue #1), this is a low-effort session store DoS vector.Security requirements for the fix:
getSession(true)call must either be removed or immediately followed by populating the SecurityContext — no intermediate state where a session exists without authenticationAudit log consideration: Should signup events be logged? Not in
admin_audit_log(that's admin actions), but a security event log that includes: timestamp, IP address, username, success/failure. Useful for detecting account creation abuse patterns.🎨 Atlas — UI/UX Designer
The fix choice here has a direct UX consequence that I want to flag as a design decision, not just a backend implementation detail.
The two paths feel very different to a user:
Auto-login after signup (Fix A): User fills out signup form, submits, lands directly in the app. Zero friction. This is the modern standard — almost every app does this. The design assumes a single flow:
signup form → onboarding/home. I'd need to design an onboarding screen (if it doesn't exist yet) that a new user sees immediately after signup.Redirect to login after signup (Fix B): User fills out signup form, gets a success message, then has to log in again. Adds one extra step. This pattern is becoming rare for consumer apps, though it's still common for more enterprise/formal flows. If we go this route, the login screen needs a "signup successful — please log in" banner state.
My recommendation: Fix A (auto-login). It removes friction at the most critical moment — first-time user activation. A user who has to log in twice after signing up has already had a worse first experience than they should.
Design questions: