Skip to content

DEF-006 — Spotify OAuth session reused across Melodex account switch

Summary

After logging out of one Melodex account and signing into another, the app continued to treat the second user as already connected to Spotify, even though that user had never granted Spotify access.
Starting an export did not prompt the Spotify login/consent screen. Instead, the export used the Spotify account from the previous Melodex user.

Environment

  • App: Melodex (local dev)
  • Commit: 4db0a3e
  • Browser: Firefox (desktop)
  • Device: Windows 11
  • Network: Spectrum (~450 up / 11 down)
  • Date/Time: 2025-11-13

Triage

  • Severity: Critical
  • Priority: High

Preconditions

  • Melodex User A is logged in and has completed Spotify OAuth (login + consent).
  • Export works normally for User A.
  • Melodex logout is performed using the app’s Google sign-out flow.

Steps to Reproduce

  1. Log in as User A (Melodex).
  2. On /rankings, click Export to Spotify
  3. Complete Spotify login and grant access when prompted.
  4. Log out of Melodex.
  5. Log in as User B (Melodex) who has never connected a Spotify account.
  6. On /rankings, click Export to Spotify

Expected Result

  • User B should be prompted to log into Spotify.
  • If User B uses a different Spotify account, that account should be associated with User B’s Melodex session.
  • /auth/session should reflect the correct authorization state for User B.

Actual Result

  • No Spotify prompt appears.
  • /auth/session immediately reports connected:true for User B.
  • Export uses User A’s Spotify account without any re-authentication.
  • No mechanism resets Spotify tokens between Melodex users.

Impact

  • Critical cross-account authorization leak.
  • Incorrect playlists may be created under the wrong Spotify user.
  • User B has access to actions that require User A’s prior authorization.
  • Violates expected OAuth isolation between users.

Owner: Michael DeReus
Status: Open
Opened: 2025-11-13
Closed: 2025-11-13

Linked Items

  • Risks:
    • R-01: Onboarding/auth failures
    • R-02: Token/session inconsistencies
    • R-19: Environment parity drift (session caching behavior)
  • Related Tests: UT-001-Auth, UT-002-Auth, UT-008-Auth, UI-001-AuthGuard, IT-001-Auth, IT-002-Auth, IT-010-Auth, E2E-003-Auth, E2E-007-Revoke

Fix Reference


Root Cause

  • Spotify provider cookies remained active after Melodex logout, preserving the previous Spotify identity.
  • Melodex logout did not invalidate backend-stored Spotify tokens or clear related cookies.
  • /auth/session did not bind authorization state to the current Melodex user ID and instead relied solely on provider cookies.
  • Export initiation relied on stale session state and did not force a fresh validation when users switched.
  • Spotify OAuth callback (/auth/callback) used multiple Set-Cookie headers.
    The second header (clearing return_to) overwrote the first header (which contained access and refresh tokens).
    As a result, Spotify tokens were never persisted in the browser, causing /auth/session to report connected:false immediately after login.

Changes

  • Consolidated all Spotify OAuth Set-Cookie operations into a single header in /auth/callback to ensure access and refresh tokens are actually stored.
  • Updated UserProfile logout flow to call /auth/revoke before Cognito logout, so Spotify tokens are cleared during explicit sign-out.
  • Added user-switch detection in UserContext (melodex_last_uid in localStorage); when a different Melodex user is detected, the frontend calls /auth/revoke to prevent cross-account Spotify session leakage.
  • Confirmed /auth/session now reflects accurate authorization state across logout, navigation, and user switching.

Verification

Initial verification steps will include:
1. Log in as User A, complete Spotify OAuth.
2. Log out via the app; confirm /auth/revoke is called.
3. Log in as User B.
4. Start export; ensure Spotify prompts login for User B.
5. Verify /auth/session only returns connected:true once User B completes OAuth.
6. After callback, confirm a second export does not trigger another OAuth prompt and no 401 (AUTH_SPOTIFY_REQUIRED) is returned.

Verified in: d52c4b0 on 2025-11-13
Verification Status: Pass