131 lines
4.1 KiB
Markdown
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)
|
|
|