ADR-003: Token Refresh Implementation Strategy
Status: Accepted
Date: 2025-09-22
Authors: Development Team
Related: ADR-002 (Token Cache Secure Storage Implementation)
Context
Following the successful implementation of secure token cache storage (ADR-002), we needed to develop a mechanism for proactive token refresh to prevent authentication interruptions. Through proof-of-concept development, we identified the working parameters and implementation approach for forcing Microsoft Teams authentication token refresh.
Problem
Microsoft Teams tokens have a 24-hour lifespan and are typically refreshed by the native Teams web application approximately 1 hour before expiry. However, for a desktop wrapper application like Teams for Linux, we need the ability to:
- Proactively refresh tokens at configurable intervals (not just before expiry)
- Force fresh token retrieval (bypass cached tokens when needed)
- Integrate with secure storage from ADR-002 implementation
- Avoid authentication interruptions during extended usage sessions
Investigation Findings
Working Token Refresh Parameters
Through systematic testing, we identified the minimal required parameters for forcing Microsoft Teams token refresh:
{
correlation: correlation, // Required - Teams correlation object
forceRenew: true, // Force new token request
forceRefresh: true, // Override cache behavior
skipCache: true, // Bypass token cache
prompt: 'none' // Silent refresh (no user interaction)
}
Key Technical Discoveries
-
Correlation Requirement: The
correlationparameter from Teams core services is mandatory for forced refresh. Without it, requests fail with "Cannot read properties of undefined (reading 'scenarioName')" error. -
Multiple Force Parameters Needed: Single parameters like
forceRenew: truealone are insufficient. The combination offorceRenew,forceRefresh, andskipCacheis required for reliable cache bypassing. -
Silent Operation: Using
prompt: 'none'ensures refresh operations don't interrupt user workflow with authentication dialogs. -
Reliable Success Indicator: Successful forced refresh returns
fromCache: falsein the result object, confirming fresh token retrieval.
Timer Implementation Strategy
Decision: Use setInterval for refresh scheduling
- Rationale: Simple, reliable, and sufficient for our needs
- Alternative Considered:
setTimeoutwith recursive calls - unnecessary complexity - Alternative Considered: Advanced scheduling systems - over-engineering for this use case
Security Considerations
Refresh Frequency Considerations:
- Frequent Refresh (1 hour default): More proactive, prevents authentication interruptions
- Less Frequent (4-6 hours): Reduces API calls, closer to native Teams behavior
- User Choice: Configurable interval allows users to balance security vs. resource usage
- Mitigation: Risk is acceptable due to secure storage implementation (ADR-001) using Electron safeStorage API
Validation Bounds:
- Minimum: 1 hour (prevent Microsoft API spam)
- Maximum: 24 hours (prevent token expiry)
- Default: 1 hour proactive strategy (balances security with usability)
Decision
Core Implementation Approach
- Use proven refresh parameters documented above for all token refresh operations
- Implement
setInterval-based scheduling for refresh timing - Integrate with TeamsTokenCache class from ADR-001 (extend, don't replace)
- Default to enabled with 1-hour interval - simple, effective configuration
Configuration Design
{
tokenRefresh: {
enabled: true, // true/false to enable/disable feature
refreshIntervalHours: 1 // 1-24 hour range
}
}
MS Teams Native Refresh Handling
Research Required: Determine whether to:
- Option A: Override native Teams refresh calls (preferred if simple)
- Option B: Run alongside native refresh (acceptable fallback)
This decision point requires additional investigation in the implementation phase.
Implementation Constraints
Must Follow Existing Patterns
- WeakMap Pattern: Use for private fields in AppConfiguration class
- [TOKEN_CACHE] Logging: Maintain consistent logging prefix
- Secure Storage Integration: Leverage existing safeStorage → localStorage → memory fallback
- Configuration Management: Use existing AppConfiguration and electron-store patterns
Development Guidelines
- No Runtime Configuration Changes: App restart required for refresh setting changes
- No Fallback Implementation: Teams handles authentication failures naturally
- Documentation-Focused: Use docs-site instead of JSDoc
- Production Logging Only: Convert debug logging to appropriate log levels
Consequences
Positive
- Reliable Token Refresh: Proven working implementation reduces authentication interruptions
- User Configurable: Allows users to customize refresh frequency based on usage patterns
- Secure: Integrates with existing secure token storage without compromising security
- Simple: Uses straightforward
setIntervalapproach for maintainable code
Negative
- Additional Complexity: Adds refresh scheduling logic to token cache system
- Resource Usage: Timer-based refresh consumes minimal system resources
- Configuration Dependency: Users must restart application to change refresh settings
Neutral
- API Usage: Proactive refresh increases Microsoft API calls (within reasonable limits)
- Dual Refresh Potential: May run alongside native Teams refresh until override investigation completed
Implementation Tasks
This ADR establishes the foundation for tasks 3.0-6.0 in tasks-prd-configurable-token-refresh.md:
- Extract proven refresh mechanism from POC implementation
- Integrate refresh scheduling with TeamsTokenCache class
- Add configuration system with validation (1-24 hour bounds)
- Clean up debug code and implement production logging
- Update documentation and architecture guides
Monitoring and Success Criteria
- Success Indicator:
fromCache: falsein refresh responses - Error Indicator: Empty error objects or correlation-related failures
- Performance: Refresh operations complete within 2-3 seconds
- Logging: Clear
[TOKEN_CACHE]prefixed logs for refresh activities
References:
- ADR-002: Token Cache Secure Storage Implementation
- POC Implementation:
app/browser/tools/reactHandler.js(triggerTokenRefresh method) - Configuration Patterns:
app/appConfiguration/index.js - Task List:
tasks/tasks-prd-configurable-token-refresh.md