🔖 Title
Fix refresh-token reuse detection and add multi-device session management
📄 Description
Refresh token rotation exists (auth.service.ts), including a token_family column and a revokeFamily() method in sessions.repository.ts. However, refreshTokens() updates the session row in place (sessionsRepository.update(session.id, ...)) instead of inserting a new row and marking the old one used. Because of this, when a stolen/old refresh token is replayed, findByHash() never matches the (now-overwritten) hash, so the flow falls into a generic "not found" error and never reaches the revoked_at !== null branch that triggers revokeFamily(). The reuse-detection security mechanism is effectively dead code.
There is also no multi-device session management: no GET /auth/sessions, no DELETE /auth/sessions/:id, no "logout all devices". device_info/ip_address columns exist on sessions but are never populated.
✅ Tasks to complete
📚 Documentation/context for AI
(This link never should removed)
https://github.com/TrustUp-app/TrustUp-API/tree/main/docs
🗒️ Additional notes
This is a security fix, not a rewrite — the schema (token_family, revoked_at) and revokeFamily() already exist and should be reused, not reinvented.
🔖 Title
Fix refresh-token reuse detection and add multi-device session management
📄 Description
Refresh token rotation exists (
auth.service.ts), including atoken_familycolumn and arevokeFamily()method insessions.repository.ts. However,refreshTokens()updates the session row in place (sessionsRepository.update(session.id, ...)) instead of inserting a new row and marking the old one used. Because of this, when a stolen/old refresh token is replayed,findByHash()never matches the (now-overwritten) hash, so the flow falls into a generic "not found" error and never reaches therevoked_at !== nullbranch that triggersrevokeFamily(). The reuse-detection security mechanism is effectively dead code.There is also no multi-device session management: no
GET /auth/sessions, noDELETE /auth/sessions/:id, no "logout all devices".device_info/ip_addresscolumns exist onsessionsbut are never populated.✅ Tasks to complete
refreshTokens()to insert a new session row per rotation and mark the previous one as used/rotated (not overwritten)revokeFamily()device_info/ip_addresson session creationGET /auth/sessions— list active sessions for current userDELETE /auth/sessions/:id— revoke a specific session/deviceDELETE /auth/sessions— logout from all devices📚 Documentation/context for AI
(This link never should removed)
https://github.com/TrustUp-app/TrustUp-API/tree/main/docs
🗒️ Additional notes
This is a security fix, not a rewrite — the schema (
token_family,revoked_at) andrevokeFamily()already exist and should be reused, not reinvented.