Test Plan: Authentication & Session Management

♻️ Reconciled against current code — 2026-07-01. This page was a bare TC index with no reconciliation notes. It's now a proper Test Plan: the org portal (stg-rcme.membervu.com) and the super-admin portal (stg-admin.membervu.com) are two separate auth systems that used to hard-expire at the access-token TTL — both now carry a refresh token (org: #359; admin: #531/#532), and as of #539/#540 the two portals' cookies no longer collide when open in the same browser. Reconciled against auth-service/src/authHandlers.ts, authMiddleware.ts, routes.ts, handlers/magicLinkHandlers.ts, handlers/platformAuthHandlers.ts, services/auth/refreshTokenService.ts, services/auth/platformRefreshTokenService.ts, utils/refreshCookie.ts, and config.ts.
🆕 New on stage — 2026-07-08 (session-scoped logout, #640, !284). See the Jul 8 release note for full test steps.
🆕 New on stage — 2026-06-19 → 2026-07-01.

1. Introduction

Authentication & Identity covers two independent login systems sharing the same backend process: the org portal (tenant users — members, admins, staff — email+password or magic link) and the super-admin / platform portal (Zeniark operators — email+password only, no magic link, no tenant binding). They use different JWT shapes, different refresh-token allow-lists, different cookies, and — as of this release window — are explicitly hardened against colliding with each other in a shared browser (#539/#540). Also in scope: password management, email verification, magic-link (passwordless) auth, and session lifecycle (expiry, refresh, multi-tab, logout).

2. Where it lives (UI)

3. Endpoints (current code)

Mounted under both /api/auth and the legacy /auth prefix (auth-service/src/server.ts); handlers in authHandlers.ts, routes.ts, handlers/magicLinkHandlers.ts, handlers/platformAuthHandlers.ts.

MethodEndpointPortalNotes
POST/api/auth/loginOrgRate-limited (authLimiter). Rejects platform-admin credentials (AUTH-04). Sets auth_token httpOnly cookie (15-min TTL) + issues a refresh token → refresh_token cookie. Body needs tenantId (slug or id).
POST/api/auth/refreshOrgReads only the refresh_token cookie (never platform_refresh_token). Rotates it (single-use) and mints a new 15-min access token. 401 on missing/invalid/already-rotated/revoked token.
POST/api/auth/logoutOrgBest-effort: revokes the specific refresh token presented; clears cookies.
GET/api/auth/meOrgReturns current user (id, email, roles, tenantId, userType).
POST/api/auth/forgot-password / /reset-password / /password/changeOrgpasswordResetLimiter / authLimiter. Password change bumps tokenVersion (revokes all other sessions).
POST/api/auth/magic-link/requestOrg (self-service)authLimiter. Always returns generic success (no email enumeration). Creates a purpose:"LOGIN" token — never reactivates an INACTIVE account.
POST/api/auth/magic-link/verifyOrgPurpose-aware (#484): SUSPENDED → always 403; INACTIVE+non-ACTIVATION → 403 ACCOUNT_DISABLED; INACTIVE+ACTIVATION → reactivates then signs in.
POST/api/membership/members/:id/activation/reissueOrg (admin action)MEMBERS:CREATE:import permission. Invalidates the member's prior outstanding tokens, mints a fresh purpose:"ACTIVATION" token, emails the activation link.
POST/api/auth/platform/loginPlatformauthLimiter. 403 NOT_PLATFORM_ADMIN for any non-platform-admin or wrong password (no distinct "wrong password" message — avoids account enumeration). Issues a 12h refresh token → platform_refresh_token cookie.
POST/api/auth/platform/refreshPlatformReads only platform_refresh_token. Dedicated endpoint — does not fall through to the tenant refresh path.
POST/api/auth/platform/logoutPlatformRevokes the whole platform refresh chain + bumps PlatformAdmin.tokenVersion (kills outstanding access tokens too, not just the refresh chain).
POST/api/auth/platform/forgot-password / /reset-passwordPlatformSeparate from tenant reset — PlatformAdmin.passwordResetToken, opaque pw-reset-<hex> tokens, no tenantId in body.
POST/api/membership/applyPublic (unauth)applicationLimiter5 / 15 min / IP (#501). 429 beyond that.

4. Session & token model

5. Environment (staging)

6. Do NOT test (features that don't exist / out of scope)

7. Test Deliverables

8. Risk Areas