fix(auth): epoch-check the target on account switch to avoid a full wallet logout (B-core-9)
POST /api/me/switch validated wallet membership, access and suspension but not the target account's session epoch. Switching to an account revoked elsewhere (a password reset/change or "log out everywhere" bumped its epoch) made it the session default, so the next request's current_user hit the epoch mismatch on the default identity and cleared the WHOLE wallet session — logging out every account in the browser. Mirror the suspend guard: drop the stale account from the switch list and return 403 instead of switching.
This commit is contained in:
@@ -72,6 +72,18 @@ def switch_account(
|
||||
# Don't make a suspended account the active one — the next request's current_user would
|
||||
# see the suspension and clear the WHOLE wallet session, logging out every account here.
|
||||
raise HTTPException(status_code=403, detail="That account is suspended.")
|
||||
# Same reasoning for a REVOKED session (a password reset/change or "log out everywhere" bumped the
|
||||
# account's epoch): making it the session default would trip current_user's epoch check on the next
|
||||
# request and clear the whole wallet. Mirror the suspend guard — drop the stale account from the
|
||||
# switch list and refuse, rather than logging everyone out. (B-core-9)
|
||||
epochs = request.session.get("epochs") or {}
|
||||
if int(epochs.get(str(target), 0)) != (u.session_epoch or 0):
|
||||
request.session["account_ids"] = [
|
||||
a for a in (request.session.get("account_ids") or []) if a != target
|
||||
]
|
||||
raise HTTPException(
|
||||
status_code=403, detail="That account was signed out elsewhere — sign in again."
|
||||
)
|
||||
request.session["user_id"] = target
|
||||
return {"ok": True, "user_id": target}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user