Skip to content

fix: prevent expired OAuth device codes in authentication flow#8

Merged
stephschofield merged 2 commits into
shyamsridhar123:mainfrom
stephschofield:main
Jan 9, 2026
Merged

fix: prevent expired OAuth device codes in authentication flow#8
stephschofield merged 2 commits into
shyamsridhar123:mainfrom
stephschofield:main

Conversation

@stephschofield
Copy link
Copy Markdown
Collaborator

@stephschofield stephschofield commented Jan 9, 2026

Problem

The authentication system was creating new OAuth device auth instances on every /auth/check request, which caused several issues:

  • Device codes only last 15 minutes per GitHub OAuth specification
  • Each new /auth/check request created a different device code
  • Frontend polling kept trying to verify expired codes instead of the original one
  • Device authentication was not persisting - the auth instance was recreated on every check
  • Users saw "expired token" errors when refreshing the auth page
  • Already authenticated users had to re-authenticate unnecessarily

Root Cause

The checkDeviceFlowAuth() function was calling createOAuthDeviceAuth() on every poll, instead of reusing the original auth instance from login. Since device codes expire after 15 minutes, and a new code was generated on each check, the original code the user authorized would expire before verification could complete.

Solution

This PR implements proper OAuth instance lifecycle management to persist device authentication:

  1. Store OAuth auth instance - Created once during initiateDeviceFlow() and stored in pendingAuth
  2. Reuse for verification - checkDeviceFlowAuth() now reuses the stored instance instead of creating new ones
  3. Early return for authenticated users - If tokens are valid, immediately return authenticated without device flow checks
  4. Clear after success - Once authenticated, clear pendingAuth and pendingVerification
  5. Graceful error handling - Expired device codes are caught and handled without throwing errors

Changes

src/services/auth-service.ts

  • Added pendingAuth variable to store OAuth instance across requests
  • Modified initiateDeviceFlow() to store and clear auth instance appropriately
  • Updated checkDeviceFlowAuth() to reuse stored auth instance
  • Enhanced error handling for expired codes
  • Updated clearTokens() to clear pending auth state

src/types/github.ts

  • Updated VerificationResponse type to support 'authenticated' status

Benefits

Device authentication persists across polling requests
Users stay authenticated on page refresh
No more expired device code errors
Single OAuth flow per login session
Better error handling and logging
Improved user experience with persistent authentication

Testing

  • ✅ Build passes
  • ✅ Lint passes
  • ✅ Authentication flow works correctly
  • ✅ Page refresh maintains authentication state
  • ✅ Expired codes handled gracefully

stephschofield and others added 2 commits January 9, 2026 10:34
Problem:
- /auth/check endpoint was creating new OAuth device auth instances on every request
- Each new instance generated a different device code
- Old device codes expired after ~15 minutes
- Frontend polling kept trying expired codes, causing authentication errors on refresh

Solution:
- Store and reuse OAuth auth instance across check requests
- Return authenticated status immediately if tokens are valid
- Clear auth instance after successful authentication
- Handle expired device codes gracefully without throwing errors
- User authentication now persists correctly on page refresh

Changes:
- auth-service.ts: Added pendingAuth storage and reuse logic
- github.ts: Updated VerificationResponse type to support authenticated status
- Improved error handling for expired codes
@stephschofield stephschofield merged commit a991769 into shyamsridhar123:main Jan 9, 2026
3 checks passed
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