TC-AUTH-005: Session Management (Detailed)
Module: Authentication & Identity - Session Management
Admin Test User: admin@rcme.membervu.com / Admin123! (Admin User)
Member Test User: testmember@rcme.membervu.com / Member123! (Maria Cruz)
Treasurer Test User: treasurer@demo.membervu.com / Treasurer123! (Ana Reyes)
Events Mgr Test User: events@demo.membervu.com / Events123! (Carlos Garcia)
Frontend:
https://stg-rcme.membervu.com
returnUrl, #346), TC-SESS-09 (open-redirect rejection, #360), TC-SESS-10 (membership-application rate limit, #501) — appended after the existing scenarios below. Do not delete the older ones.
TC-SESS-01: Login and Logout Flow
Purpose: Verify the basic login and logout flow works correctly.
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | Open your browser and go to:https://stg-rcme.membervu.com/login |
The MemberVu login page loads with Email and Password fields and a "Sign In" button. | https://stg-rcme.membervu.com/login |
| 2 | Enter email: admin@rcme.membervu.comEnter password: Admin123!Click "Sign In". |
Login succeeds. The admin dashboard loads. You see admin navigation items in the sidebar (e.g., "Admin", "Members", "Settings"). | Email: admin@rcme.membervu.comPassword: Admin123! |
| 3 | Click on your user avatar or name in the top-right corner of the page to open the user menu. | A dropdown menu appears with options like "Profile", "Settings", and "Logout" (or "Sign Out"). | - |
| 4 | Click "Logout" (or "Sign Out"). | You are redirected to the login page:https://stg-rcme.membervu.com/login |
- |
| 5 | Try to access a protected page directly by entering this URL:https://stg-rcme.membervu.com/dashboard |
You are redirected back to the login page. You cannot access the dashboard without logging in. | https://stg-rcme.membervu.com/dashboard |
TC-SESS-02: Session Persistence (Tab Reopen)
Purpose: Verify that a session persists when closing and reopening a browser tab.
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | Go to https://stg-rcme.membervu.com/loginEnter email: admin@rcme.membervu.comEnter password: Admin123!Click "Sign In". |
Login succeeds. Dashboard loads. | Email: admin@rcme.membervu.comPassword: Admin123! |
| 2 | Close the browser tab (NOT the entire browser window — just the tab). Do NOT log out first. | The tab closes. | - |
| 3 | Open a new tab in the same browser. Go to:https://stg-rcme.membervu.com/dashboard |
The dashboard loads WITHOUT requiring you to log in again. Your session persisted via localStorage. | https://stg-rcme.membervu.com/dashboard |
| 4 | Log out from this new tab. | Redirected to login page. | - |
TC-SESS-03: Multi-Tab Session
Purpose: Verify that authentication state is shared across multiple browser tabs.
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | In Tab 1, go to:https://stg-rcme.membervu.com/loginEnter email: admin@rcme.membervu.comEnter password: Admin123!Click "Sign In". |
Login succeeds in Tab 1. Dashboard loads. | Email: admin@rcme.membervu.comPassword: Admin123! |
| 2 | Open a new Tab 2 in the same browser. Go to:https://stg-rcme.membervu.com/dashboard |
Tab 2 also shows the dashboard — you are authenticated in both tabs because the session token is stored in localStorage (shared across tabs). | https://stg-rcme.membervu.com/dashboard |
| 3 | In Tab 1, click the user menu and click "Logout". | Tab 1 redirects to the login page. | - |
| 4 | Switch to Tab 2. Click on any navigation link (e.g., "Members" or "Profile") to trigger a page navigation or API call. | Tab 2 should detect the logout. It will either: - Automatically redirect to the login page, or - Show an "Unauthorized" error and redirect to login, or - Show the login page on the next navigation. The user should NOT be able to continue using the app in Tab 2 after logging out in Tab 1. |
- |
TC-SESS-04: Expired Session
What would happen: When the JWT access token expires, the next API call would return a 401 Unauthorized response. The frontend would either:
- Attempt to refresh the token using a refresh token (if implemented), or
- Redirect the user to the login page with a message like "Your session has expired. Please log in again."
TC-SESS-05: Role-Based Menu Visibility
Purpose: Verify that different roles see different navigation menus and access levels.
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | Go to https://stg-rcme.membervu.com/loginEnter email: admin@rcme.membervu.comEnter password: Admin123!Click "Sign In". |
Admin dashboard loads. The sidebar shows admin-specific navigation items such as: - "Admin" section or menu - "Members" (admin view) - "Settings" - "Billing" / "Invoices" - "Communications" / "Broadcasts" |
Email: admin@rcme.membervu.comPassword: Admin123! |
| 2 | Note the navigation items visible to the admin. Write them down or take a screenshot. Then click "Logout". | Redirected to login page. | - |
| 3 | Log in as a regular member: Email: testmember@rcme.membervu.comEnter password: Member123!Click "Sign In". |
Member dashboard loads. The sidebar shows member-specific navigation items such as: - "Dashboard" - "My Profile" - "Member Directory" - "My Invoices" Admin-specific items (like "Admin", "Settings", "Communications") should NOT be visible. |
Email: testmember@rcme.membervu.comPassword: Member123! |
| 4 | Verify the "Admin" menu or section is NOT visible in the sidebar. Log out. | The Admin section is not shown to a regular member. | - |
| 5 | Log in as treasurer: Email: treasurer@demo.membervu.comEnter password: Treasurer123!Click "Sign In". |
Dashboard loads. The sidebar shows treasurer-specific items. You should see billing/financial related menu items. Admin-only items may or may not be visible depending on the Treasurer's permissions. | Email: treasurer@demo.membervu.comPassword: Treasurer123! |
| 6 | Note any unique menu items visible to the Treasurer role. Log out. | Treasurer-specific navigation noted. | - |
| 7 | Log in as events manager: Email: events@demo.membervu.comEnter password: Events123!Click "Sign In". |
Dashboard loads. The sidebar shows event management items. You should see "Events" or event-related menu items. | Email: events@demo.membervu.comPassword: Events123! |
| 8 | Note any unique menu items visible to the Events Manager role. Log out. | Events Manager-specific navigation noted. | - |
TC-SESS-06: Clear Cookies Forces Re-Login
Purpose: Verify that clearing browser storage forces the user to log in again.
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | Log in as admin: Email: admin@rcme.membervu.comPassword: Admin123! |
Dashboard loads. | Email: admin@rcme.membervu.comPassword: Admin123! |
| 2 | Open the browser's Developer Tools (press F12 or right-click > "Inspect"). Go to the "Application" tab (Chrome) or "Storage" tab (Firefox). Under "Local Storage", find the entry for https://stg-rcme.membervu.com.Delete all localStorage entries (right-click > "Clear" or select each key and press Delete). |
The localStorage entries are cleared (including oneledger_session, oneledger_session_user, app-tenant). |
- |
| 3 | Refresh the page (press F5). | You are redirected to the login page. The session tokens were stored in localStorage, and clearing them forces re-authentication. | - |
TC-SESS-07: Deactivate Revokes Sessions Immediately (#446)
Purpose: Verify a deactivated user's still-unexpired access token is rejected on its next request via tokenVersion, not just when the JWT itself expires.
testmember@rcme.membervu.com) — it will break other testers' sessions/tests. Create or use a throwaway test member for this scenario, and reactivate it afterward (see cleanup).
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | Browser A: Log in as a throwaway ACTIVE test member (not a shared seed account). Leave the tab open and signed in. | Login succeeds; dashboard loads. | A disposable/test member you created, currently status ACTIVE |
| 2 | Browser B (separate session): Log in as admin@rcme.membervu.com / Admin123!. Go to Members, open the same member from Step 1, click Deactivate (calls POST /api/membership/members/:id/deactivate). |
Confirmation succeeds; the member's status shows Inactive in the admin list. | Email: admin@rcme.membervu.comPassword: Admin123! |
| 3 | Immediately switch back to Browser A (do NOT wait ~15 min for the access token to naturally expire) and click any navigation link, or refresh the page (e.g. go to /dashboard or trigger any API call such as viewing your profile). |
The request returns 401 Unauthorized and you are redirected to the login page — immediately, not after a TTL wait. This proves revocation is via tokenVersion check, not JWT expiry. |
- |
TC-SESS-08: Deep-Link returnUrl Preserved Through Login (#346)
Purpose: Verify a protected deep link visited while logged out is preserved and honored after login, instead of dumping the user on the generic role-based landing page.
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | Make sure you are logged out (clear localStorage / cookies if needed). Navigate directly to:https://stg-rcme.membervu.com/admin/members |
You are redirected to the login page with the original path preserved in the query string:https://stg-rcme.membervu.com/login?redirect=%2Fadmin%2Fmembers |
/admin/members |
| 2 | Enter email: admin@rcme.membervu.comEnter password: Admin123!Click "Sign In". |
Login succeeds and you land directly on /admin/members — the deep-linked page — NOT on the role-based default (/admin/dashboard). |
Email: admin@rcme.membervu.comPassword: Admin123! |
| 3 | Log out. Repeat Steps 1–2 with a different deep link, e.g. /admin/broadcasts, logging in as comms@demo.membervu.com / Comms123! this time. |
Again lands on the exact deep-linked page (/admin/broadcasts), confirming this isn't a one-off/hardcoded path. |
Email: comms@demo.membervu.comPassword: Comms123! |
TC-SESS-09: Open-Redirect Rejection (#360)
Purpose: Verify a maliciously-crafted redirect query param cannot send a logged-in user off-site.
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | Log out. Navigate to:https://stg-rcme.membervu.com/login?redirect=%2F%5Cevil.com(URL-decoded, the redirect value is /\evil.com — a backslash path.) |
The login page loads normally — no crash, no error banner. | redirect=%2F%5Cevil.com |
| 2 | Enter email: testmember@rcme.membervu.comEnter password: Member123!Click "Sign In". |
Login succeeds. You land on a safe same-site page (/home or the member's role-based default) — you are NOT sent to evil.com or any external host. Check the address bar to confirm the host is still stg-rcme.membervu.com. |
Email: testmember@rcme.membervu.comPassword: Member123! |
| 3 | Log out. Repeat with ?redirect=https%3A%2F%2Fevil.com (absolute URL) and then ?redirect=%2F%2Fevil.com (protocol-relative, no scheme). |
Both also resolve to a safe same-site page after login — no off-site redirect in either case. | redirect=https%3A%2F%2Fevil.comredirect=%2F%2Fevil.com |
evil.com after login.
TC-SESS-10: Membership-Application Rate Limit (#501)
Purpose: Verify the public, unauthenticated membership-application endpoint is throttled to prevent spam.
| Step | Action (EXACT clicks/typing) | Expected Result (EXACT text/behavior) | Test Value |
|---|---|---|---|
| 1 | While logged out, go to the public membership application page and submit one valid application (calls POST /api/membership/apply). |
Application submits successfully (200/201). |
Any valid applicant details |
| 2 | Immediately submit 4 more valid applications back-to-back from the same browser/IP (5 total so far in this 15-min window). | All 5 succeed. If you can inspect response headers, RateLimit-Remaining counts down toward 0. |
- |
| 3 | Submit a 6th application within the same 15-minute window. | Rejected with 429 Too Many Requests — message indicates too many attempts. The application is NOT created. |
- |
| 4 | (Local only, to reset) Run docker restart membervu-backend. |
In-memory limiter clears; a new application succeeds again. (Not available on staging — wait out the 15-min window there instead.) | - |
CLEANUP — Read This Before You Stop
- TC-SESS-07: Reactivate the throwaway test member you deactivated (Admin → Members → find the member → Reactivate), or simply discard the disposable test account if it's not reused elsewhere. Do NOT leave a shared seed account deactivated.
- TC-SESS-10: The 5+ test membership applications you submitted will exist as real
MembershipApplicationrows — delete/reject them via Admin → Membership Applications if your tenant is shared with other testers.
Ensure you are fully logged out of both Browser A and Browser B before finishing.