Skip to content

Fix/device auth review followup - #225

Merged
2witstudios merged 7 commits into
masterfrom
fix/device-auth-review-followup
Jan 21, 2026
Merged

2witstudios merged 7 commits into
masterfrom
fix/device-auth-review-followup

Conversation

@2witstudios

@2witstudios 2witstudios commented Jan 21, 2026 •

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added device token persistence with enhanced error handling for improved session recovery.
  • Bug Fixes

    • Improved token refresh retry logic to gracefully pause instead of forcing logout on max attempts.
    • Extended token refresh recovery to web sessions for better consistency across platforms.

✏️ Tip: You can customize this high-level summary in your review settings.

2witstudios and others added 6 commits January 20, 2026 13:09
This PR addresses issues found in code review and adds comprehensive
device token persistence for web browsers.

## Auth Loop Prevention
- Add `authFailedPermanently` flag to break Zustand rehydration loops
- Add `authAttemptTimestamps` for rapid auth attempt detection (5+ in 10s)
- Clear failure flags on successful session load (OAuth/login flow fix)
- Set permanent failure flag when device token is definitively revoked

## Device Token Linking
- Link device tokens to refresh tokens in OAuth callback and One Tap
- Ensures device revocation also revokes associated refresh tokens
- Prevents revoked devices from refreshing via orphaned refresh tokens

## Web Device Token Persistence
- Extend device token creation to web platform (was desktop-only)
- Pass deviceId and deviceName from browser to OAuth endpoints
- Store web device token in localStorage for 90-day persistence
- Add fingerprint utility integration for web device identification

## Desktop Auth Improvements
- Reduce JWT cache TTL from 30s to 5s for freshness after rotation
- Clear `authFailedPermanently` on login attempt in useAuth hook

## Tests
- Add comprehensive tests for auth loop detection
- Add tests for web device token creation in One Tap and OAuth callback
- Add tests for `authFailedPermanently` flag behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The useAuth hook calls useAuthStore.getState().setAuthFailedPermanently()
during login, but the test mock was missing this method causing CI failures.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Prevent attackers from hijacking OAuth callbacks to external domains:

- Validate returnUrl in signin to reject absolute/protocol-relative URLs
- Defense-in-depth: re-validate returnUrl in callback before redirect
- Add localStorage error handling in GoogleOneTap for private browsing
- Add comprehensive tests for redirect protection

Attack vector prevented: attacker sets returnUrl to external domain,
tricks victim through OAuth, captures deviceToken from redirect.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Wrap decodeURIComponent() in try-catch to handle malformed percent-encoding
gracefully. Without this, URLs like /%E0%A4%A would throw URIError instead
of being rejected as unsafe. This matches the pattern already used in
callback/route.ts for defense-in-depth.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add token refresh attempt before marking auth as failed in useAuthStore
- Persist device token after successful refresh in auth-fetch
- Track shouldLogout flag to distinguish fatal vs transient failures
- Pause retry attempts instead of forcing logout on max retries
- Update test mock to include shouldLogout in refreshAuthSession response

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jan 21, 2026 •

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

The pull request enhances token refresh logic by introducing refresh outcome tracking to control retry behavior, adding device token and CSRF token persistence from device-token fallback responses with error handling, and implementing a web-token refresh flow in the auth store that mirrors desktop behavior for improved session recovery without forced logout on temporary failures.

Changes

Cohort / File(s) Summary
Refresh Outcome Tracking
apps/web/src/hooks/useTokenRefresh.ts
Added lastRefreshResultRef to track refresh success/shouldLogout state; modified retry logic to abort further retries when shouldLogout is true; changed max-retry behavior from immediate logout to pausing refresh attempts and resetting retry counter.
Device Token & CSRF Persistence
apps/web/src/lib/auth/auth-fetch.ts
Implemented parsing and localStorage persistence of deviceToken and csrfToken from device-token-based refresh responses in both web and desktop paths; added error handling for storage failures with warning logs; logs session recovery via device token fallback.
Auth Store Session Recovery
apps/web/src/stores/useAuthStore.ts
Added web-token refresh flow mirroring desktop behavior: on token validation failure, conditionally attempts refresh via refreshAuthSession and retries session load on success; on non-fatal failure increments failedAuthAttempts and tracks last failed auth check.
Test Mock Update
apps/web/src/stores/__tests__/useAuthStore.test.ts
Updated mocked refreshAuthSession return value to include shouldLogout: true field alongside success: false.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

Poem

🐰 A token refresh dance, oh what a sight,
Device tokens saved, CSRF locked tight!
When refresh attempts stumble and retry,
Smart logout decisions—no more quick goodbye! 🔐

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@2witstudios
2witstudios merged commit 3aee0e9 into master Jan 21, 2026
5 of 7 checks passed
@2witstudios
2witstudios deleted the fix/device-auth-review-followup branch January 29, 2026 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant