Full technical details in your project at
/docs/modules/Auth.mdWhat You Get
- ✅ 3 auth providers - Apple, Google, Email (all via Supabase)
- ✅ Reliable session persistence - Users stay logged in for days, not hours
- ✅ Automatic token refresh - Silent background refresh keeps sessions alive
- ✅ Expired session recovery - Refresh tokens restore sessions even after access token expires
- ✅ Keychain storage - Secure, encrypted token persistence
- ✅ AsyncStream state - Observable authentication state (including
.refreshing) - ✅ MockAuthClient - DEBUG mode works without backend
Module structure (since v2.0)
SessionManageris split across four files:SessionManager.swift,SessionManager+SignIn.swift,SessionManager+Refresh.swift, andSessionManager+Persistence.swift. The public actor API is unchanged. This is the ≤ 400-line rule in action.SupabaseAuthAPIhelpers moved toSupabaseAuthAPI+Mapping.swift. Private helpers only; no API change.- All protocol-typed properties now use the explicit
anykeyword required by Swift 6.
Session Behavior
Users only need to re-authenticate when the refresh token expires (7+ days by default, configurable in Supabase).
Key Components
AuthClient Protocol
Production Setup (From Real Code)
How authentication is set up inCompositionRoot.swift:
What SessionManager Does
On App Launch:- Loads session from Keychain
- Validates token expiry
- Auto-refreshes if expiring soon
- Emits
.authenticatedor.unauthenticatedstate
- Exchanges provider token with Supabase
- Saves access + refresh tokens to Keychain
- Schedules proactive refresh
- Emits
.authenticated(user)state
- Scheduled 60s before token expiry
- Recovers expired sessions using refresh token
- Retries up to 3 times with exponential backoff
- Handles Supabase token rotation
- Users stay logged in for days, not hours
- ✅ Race-safe refresh mutex
- ✅ Cancellation-aware
- ✅ Comprehensive error handling
- ✅ Fully tested (85%+ coverage)
Token Management
Automatic Refresh
Secure Storage
All tokens stored in Keychain:- ✅ Access token
- ✅ Refresh token
- ✅ Never in UserDefaults
- ✅ OS-level encryption
Auth State Observation
Customization Examples
Add a Social Provider
Apple and Email ship wired out of the box. Google is implemented in the package (GoogleSignInCoordinator) but is not wired in CompositionRoot by default —
pass a Google provider to SessionManager(google:) to enable it. To add another
provider, declare it on AuthClient and implement it on the production client
(SessionManager, in SessionManager+SignIn.swift):
Add Custom Fields
Mock Auth in DEBUG
Enabled by default! No setup needed.CompositionRoot selects the mock at startup. In DEBUG it uses MockAuthClient
unless AUTH_BYPASS=0 is set; in RELEASE the mock is compiled out entirely.
- Edit Scheme → Run → Environment Variables
- Add
AUTH_BYPASS=0 - Configure Supabase in
Config/Secrets.xcconfig
Key Files
Dependencies
- Core - Error handling, logging
- Networking - HTTP client (for Supabase)
Used By
- All features - Protected by authentication
- CompositionRoot - Observes auth state
- LaunchRouter - Auth-gated navigation
Best Practices
Token Security
Token Security
- Always store in Keychain
- Never log tokens
- Refresh before expiry
- Clear on sign out
Error Handling
Error Handling
- Map to AppError
- User-friendly messages
- Retry transient failures
- Log technical details
Testing
Testing
- Use MockAuthClient
- Test token refresh
- Test error scenarios
- Test state transitions
Learn More
Full Documentation
Complete Auth guide
Supabase Setup
Configure backend
Building Guide
Customize auth flow
Architecture
See auth in system
Test Coverage
85%+ - Comprehensive auth testing (run via theAuthTests target in the single Boilerplate.xctestplan pass)
Tests include:
- Sign in/up flows
- Token refresh
- Session management
- Apple Sign In coordination
- Error scenarios
- State transitions
