NeahNew/MICROSOFT_OAUTH_FIXES.md
2026-01-01 19:31:48 +01:00

131 lines
4.1 KiB
Markdown

# Microsoft OAuth Token Management - Fixes Applied
## Issues Fixed
### ✅ Fix #1: Refresh Tokens Now Persisted to Prisma Database
**Problem**: Refresh tokens were only stored in Redis (24-hour TTL), risking permanent loss.
**Solution**:
- Refresh tokens are now saved to `MailCredentials.refresh_token` in Prisma
- Access tokens and expiry also persisted to database
- Database acts as source of truth for long-term token storage
**Files Modified**:
- `lib/services/email-service.ts` - `saveUserEmailCredentials()` now saves OAuth tokens to Prisma
### ✅ Fix #2: Database Updated on Token Refresh
**Problem**: When tokens were refreshed, only Redis was updated, leaving database stale.
**Solution**:
- Token refresh now updates both Redis AND Prisma
- New refresh tokens (if provided by Microsoft) are persisted
- Token expiry timestamp updated in database
**Files Modified**:
- `lib/services/token-refresh.ts` - `ensureFreshToken()` now updates Prisma after refresh
### ✅ Fix #3: Fallback to Database if Redis Missing
**Problem**: If Redis cache was empty, system couldn't recover refresh tokens.
**Solution**:
- If Redis cache miss, system checks Prisma database
- Retrieves refresh token from database
- Re-populates Redis cache for future use
**Files Modified**:
- `lib/services/token-refresh.ts` - Added database fallback logic
### ✅ Fix #4: OAuth Fields Retrieved from Database
**Problem**: When loading credentials from database, OAuth fields were ignored.
**Solution**:
- Database queries now include OAuth fields (`access_token`, `refresh_token`, `token_expiry`, `use_oauth`)
- Credentials object properly populated with OAuth data from database
**Files Modified**:
- `lib/services/email-service.ts` - `getImapConnection()` now includes OAuth fields from database
## Token Storage Strategy (Current)
### Access Tokens
- **Primary**: Redis (fast access, 24-hour TTL)
- **Backup**: Prisma Database (persisted)
- **Lifespan**: ~1 hour (Microsoft default)
### Refresh Tokens
- **Primary**: Prisma Database (persistent, long-term)
- **Cache**: Redis (24-hour TTL, for fast access)
- **Lifespan**: Up to 90 days (with `offline_access` scope)
### Token Expiry
- **Storage**: Both Redis and Prisma
- **Purpose**: Determine when to refresh tokens
## Long-Term Viability
### ✅ NOW VIABLE for Production
**Improvements**:
1. ✅ Refresh tokens persisted to database
2. ✅ Database updated on token refresh
3. ✅ Fallback mechanism if Redis fails
4. ✅ No data loss on Redis restart
5. ✅ Recovery mechanism in place
## What Happens Now
### When Adding Microsoft Account:
1. OAuth tokens saved to **both** Redis and Prisma
2. Refresh token stored in database for long-term access
3. Access token cached in Redis for fast retrieval
### When Token Expires:
1. System checks Redis first (fast path)
2. If Redis miss, checks Prisma database (fallback)
3. Uses refresh token to get new access token
4. Updates **both** Redis and Prisma with new tokens
5. Continues normal operation
### If Redis is Cleared:
1. System detects Redis cache miss
2. Retrieves refresh token from Prisma database
3. Gets new access token using refresh token
4. Re-populates Redis cache
5. **No user action required**
## Testing Recommendations
1. **Test Token Refresh**:
- Wait for access token to expire (~1 hour)
- Verify system automatically refreshes
- Check both Redis and Prisma are updated
2. **Test Redis Failure**:
- Clear Redis cache
- Try to access email
- Verify system recovers from database
3. **Test Long-Term Access**:
- Wait several days
- Verify refresh token still works
- Check no re-authentication required
## Monitoring
Watch for these log messages:
-`Token for ${email} persisted to Prisma database` - Token saved successfully
-`Recovered credentials from Prisma and cached in Redis` - Fallback working
- ⚠️ `Error persisting tokens to database` - Database update failed (check logs)
## Next Steps
1. **Monitor**: Watch logs for token refresh operations
2. **Verify**: Check Prisma database has `refresh_token` values
3. **Test**: Verify email access works after Redis restart
4. **Optional**: Consider encrypting tokens at rest (if compliance requires)