fix: Mobile login redirects to homepage without showing Auth0 login page #188
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bug Description
Mobile login is broken. Tapping the "Login" button on the homepage causes the screen to flash and immediately redirect back to the homepage. The Auth0 login page never appears. Desktop login works correctly.
Steps to Reproduce
Expected Behavior
Tapping "Login" should redirect to the Auth0 login page, allow the user to authenticate, then redirect back to the app callback URL.
Environment
Investigation Findings
Loki Logs (staging, last 1h)
auth-DXZD2WD1.js,auth.api-C28lcCvZ.js)/run/secrets/resend-webhook-secret(unrelated to auth)Code Analysis
Likely root cause: Auth0 SDK detects stale cached tokens in IndexedDB, evaluates
isAuthenticatedastrue, and the app routes back to the homepage instead of triggering the Auth0 redirect.Key files involved:
frontend/src/core/auth/Auth0Provider.tsx- Auth0 config + TokenInjector with mobile-specific retry logicfrontend/src/core/utils/indexeddb-storage.ts- IndexedDB token storage (primary cache)frontend/src/core/auth/auth-gate.ts- Auth initialization gate + request queuefrontend/src/core/auth/useLogout.ts- Logout hook (only accessible from Settings)frontend/src/pages/HomePage.tsx- Login button triggersloginWithRedirect()frontend/src/App.tsx- Mobile detection (line 371) and routingContributing factors:
Auth0Provider.tsxusesuseRefreshTokens={true}anduseRefreshTokensFallback={true}- expired refresh tokens in IndexedDB may cause Auth0 SDK to think user is authenticated without a valid sessionisAuthenticatedfrom Auth0 hook may returntruefrom cache before actually validating the tokenProposed Fix (Two Parts)
Part 1: Fix mobile login redirect
loginWithRedirect()completes without showing Auth0 page on mobileisAuthenticatedis incorrectlytruefrom stale IndexedDB cacheisAuthenticatedon mobilegetAccessTokenSilently()failsPart 2: Add pre-auth logout/clear mechanism
Acceptance Criteria
Plan: fix: Mobile login redirects to homepage without showing Auth0 login page (#188)
Phase: Planning | Agent: Orchestrator | Status: AWAITING_REVIEW
Root Cause Analysis
Two interrelated issues cause the mobile login failure:
1. Stale Token Misdirection (Primary)
Auth0 SDK reads expired tokens from IndexedDB cache and temporarily evaluates
isAuthenticated = true. When the user taps "Login",handleAuthAction()inHomePage.tsx:24seesisAuthenticated = trueand callsnavigate('/garage')instead ofloginWithRedirect(). The tokens then fail validation,isAuthenticatedreverts tofalse, andApp.tsx:602redirects back to/. The Auth0 login page never appears.2. Callback Route Guard Too Strict (Secondary)
App.tsx:545requiresisCallbackRoute && isAuthenticatedto render CallbackPage. If Auth0 SDK hasn't finished processing the code exchange whenisLoadingbecomesfalse, the user on/callbackhits the!isAuthenticatedguard at line 602 and gets redirected to/.Sub-Issues
frontend/src/App.tsxfrontend/src/core/auth/Auth0Provider.tsx,frontend/src/core/utils/indexeddb-storage.tsfrontend/src/pages/HomePage.tsxMilestone 1: Fix callback route handling in App.tsx (refs #189)
File:
frontend/src/App.tsxProblem: Lines 545 and 602 create a race condition where
/callbackroute redirects to homepage before Auth0 finishes code exchange.Current flow (lines 545, 602):
Fix: Replace the single callback check with a two-branch handler:
This ensures
/callbacknever falls through to the!isAuthenticatedredirect.Milestone 2: Detect and clear stale IndexedDB auth tokens (refs #190)
Files:
frontend/src/core/auth/Auth0Provider.tsx,frontend/src/core/utils/indexeddb-storage.tsProblem: Auth0 SDK reads expired tokens from IndexedDB, sets
isAuthenticated = truefrom cache, andhandleAuthAction()navigates to/garageinstead of callingloginWithRedirect().Fix in Auth0Provider.tsx (TokenInjector):
Add a stale token detection effect that runs when
isAuthenticatedtransitions totrue:Fix in indexeddb-storage.ts:
Add
clearAll()method to the IndexedDBStorage class:Milestone 3: Add pre-auth session clear on HomePage (refs #192)
File:
frontend/src/pages/HomePage.tsxProblem: Users stuck in auth limbo have no self-recovery mechanism. Logout is only accessible from Settings, which requires authentication.
Fix: Add a "Trouble logging in?" text link below the Login button:
UI: Subtle text link styled consistently with the existing design:
Acceptance Criteria Mapping
Execution Order
M1 (callback guard) -> M2 (stale token detection) -> M3 (homepage clear)
M1 is the most critical fix. M2 prevents the root cause. M3 provides user self-recovery.
Verdict: AWAITING_REVIEW | Next: Plan review cycle (QR plan-completeness)
QR Review: plan-completeness
Phase: Plan-Review | Agent: Quality Reviewer | Status: PASS_WITH_CONCERNS
Findings
[RULE 1] [HIGH]: Missing mobile-specific test scenarios
[RULE 1] [MEDIUM]: M3 UI placement needs responsive detail
[RULE 2] [SHOULD_FIX]: Edge case - session clear on /callback route
[RULE 1] [LOW]: Desktop regression not explicitly mapped
Considered But Not Flagged
Verdict: PASS_WITH_CONCERNS (all concerns addressed) | Next: TW plan-scrub
TW Review: plan-scrub
Phase: Plan-Review | Agent: Technical Writer | Status: NEEDS_CHANGES
Findings (11 contaminated comments)
7 WHAT comments (DELETE): Self-documenting code needs no narration
// Auth0 code exchange complete - render callback handler// Auth0 still processing code exchange - show loading state// Force fresh token validation (bypass cache)// Clear IndexedDB cache// Reset Auth0 SDK state - logout without redirect// Clear IndexedDB auth cache// Clear localStorage auth items// Reset Auth0 SDK state1 Location directive (DELETE):
// Handle callback route - MUST be before !isAuthenticated guard2 Temporal contamination (FIX):
// Stale token detection - validate that isAuthenticated is backed by a real token->// Validate that isAuthenticated is backed by a valid token// Force page reload as fallback->// Page reload clears any remaining in-memory auth stateRevised Code Snippets
M1 (App.tsx) - all comments removed:
M2 (Auth0Provider.tsx) - one cleaned comment retained:
M3 (HomePage.tsx) - one cleaned comment retained:
Verdict: NEEDS_CHANGES (applied above) | Next: QR plan-code
QR Review: plan-code
Phase: Plan-Review | Agent: Quality Reviewer | Status: NEEDS_CHANGES
Findings
[RULE 0] [CRITICAL]: Missing
logoutdestructuring in TokenInjector (M2)getAccessTokenSilently, isAuthenticated, isLoading, userfromuseAuth0(). Plan callslogout()without importing it.logoutto destructuring at line 60.[RULE 0] [CRITICAL]: Missing
logoutdestructuring in HomePage (M3)loginWithRedirect, isAuthenticatedfromuseAuth0(). Plan callslogout()without importing it.logoutto destructuring at line 9.[RULE 0] [CRITICAL]: Infinite loop risk in token validation effect (M2)
logout({ openUrl: false }),isAuthenticatedcould toggle back totrue, re-triggering the effect.validatingRefguard to prevent re-entry:[RULE 1] [HIGH]: Missing mobile-specific callback loading state (M1)
isLoadingcheck (lines 523-541) uses different UI for mobile (Layout wrapper) vs desktop.[RULE 2] [SHOULD_FIX]: clearAll() memoryCache cleared before DB transaction (M2)
this.memoryCache.clear()insidetx.oncompletecallback.[RULE 0] Race condition between clearAll and logout: The
awaitkeyword beforeclearAll()ensures the transaction completes before logout executes. Not an issue with current async/await usage.Revised Plan Code (all fixes applied)
M1 (App.tsx):
M2 (Auth0Provider.tsx TokenInjector):
logoutto useAuth0 destructuringvalidatingRefguard to prevent infinite loopM2 (indexeddb-storage.ts clearAll):
M3 (HomePage.tsx):
logoutto useAuth0 destructuringVerdict: NEEDS_CHANGES (all fixes specified above) | Next: QR plan-docs
QR Review: plan-docs
Phase: Plan-Review | Agent: Quality Reviewer | Status: NEEDS_CHANGES (minor)
Findings
Comment rewording (M2 Auth0Provider.tsx):
// Validate that isAuthenticated is backed by a valid token// Prevent stale session state when cached token is no longer validComment deletion (M3 HomePage.tsx):
// Page reload clears any remaining in-memory auth statewindow.location.reload()in a catch block is self-documenting as a last-resort fallbackFinal Comment Inventory (2 total)
// Prevent stale session state when cached token is no longer validconsole.warn('[Auth] Stale token detected, clearing auth state')(log message, not comment)Verdict: NEEDS_CHANGES (applied) | Next: Plan approved - ready for execution
Plan Review Cycle Summary
logoutimports,validatingRefguard, mobile callback UI, clearAll() orderingPlan review cycle COMPLETE. Plan APPROVED for execution.
Milestone: M1 - Fix callback route handling in App.tsx
Phase: Execution | Agent: Frontend Agent | Status: PASS
Changes
frontend/src/App.tsxisCallbackRoute && isAuthenticatedcheck with two-branch handler/callbackand authenticated: renders CallbackPage/CallbackMobileScreen as before/callbackand not yet authenticated: shows "Processing login..." loading state (mobile uses Layout wrapper, desktop uses min-h-screen)!isAuthenticatedguard, preventing premature redirect during Auth0 code exchangeCommit
a195fa9- fix: allow callback route to complete Auth0 code exchange (refs #189)Verdict: PASS | Next: M2 execution
Milestone: M2 - Detect and clear stale IndexedDB auth tokens
Phase: Execution | Agent: Frontend Agent | Status: PASS
Changes
File:
frontend/src/core/utils/indexeddb-storage.tsclearAll()method to IndexedDBStorage classtx.oncompletecallback (prevents inconsistent state if IDB transaction fails)File:
frontend/src/core/auth/Auth0Provider.tsxlogouttouseAuth0()destructuring in TokenInjectorvalidatingRefguard to prevent infinite loop ifisAuthenticatedtogglesisAuthenticatedbecomestrue, validates token viagetAccessTokenSilently({ cacheMode: 'off' })login_required,consent_required, orinvalid_granterrors: clears IndexedDB cache and callslogout({ openUrl: false })getAccessTokenSilentlyandlogoutto effect dependency array (lint clean)Commits
6e493e9- fix: detect and clear stale IndexedDB auth tokens (refs #190)15128bf- fix: add missing hook dependencies for stale token effect (refs #190)Verdict: PASS | Next: M3 execution
Milestone: M3 - Add pre-auth session clear on HomePage
Phase: Execution | Agent: Frontend Agent | Status: PASS
Changes
frontend/src/pages/HomePage.tsxlogouttouseAuth0()destructuringhandleClearSession(): clears IndexedDB auth cache viaclearAll(), removes@@auth0localStorage items, resets Auth0 SDK state vialogout({ openUrl: false })window.location.reload()if clearing failsCommit
723e25e- fix: add pre-auth session clear mechanism on HomePage (refs #192)Verdict: PASS | Next: QR post-implementation review