- Apple Sign In - Native iOS authentication
- Google Sign In - OAuth via Google
- Email/Password - Traditional email authentication
Features
Unified Sign In Experience
- Single Sign In Screen: All authentication options on one screen
- Social OAuth: Apple and Google sign in via Supabase Auth
- Email Authentication: Sign up and sign in with email/password
- Password Reset: Forgot password flow via email
Session Persistence
✅ Users stay logged in for days, not hours - Production-ready session management that just works The app implements battle-tested session persistence:- Keychain Storage: Auth tokens are securely stored in iOS Keychain
- Automatic Session Loading: When the app launches, sessions are restored from Keychain
- Expired Session Recovery: Even if access token has expired, the app automatically refreshes using the refresh token
- Proactive Refresh: Tokens are refreshed 60 seconds before expiry
- Retry Logic: Failed refresh attempts retry up to 3 times with exponential backoff
Session Behavior
| Scenario | Behavior |
|---|---|
| App opened after 1 hour | ✅ Silent refresh, user stays logged in |
| App opened after 3 days | ✅ Silent refresh, user stays logged in |
| App opened after 14+ days | Refresh token expired, user must sign in again |
Refresh token lifetime is configurable in your Supabase dashboard. Default is 7+ days.
Session Lifecycle
Setup
1. Configure Supabase
Enable Social Providers
- Go to Supabase Dashboard
- Select your project
- Navigate to Authentication → Providers
Apple Sign In Setup (Step-by-Step)
1
Step 1: Go to Supabase Authentication
In your Supabase dashboard, navigate to Authentication settings. This is where you’ll enable Apple as a sign-in provider.
2
Step 2: Enable Apple Sign In Provider
Go to Sign In Providers and find Apple in the list. Click on it to configure.
3
Step 2.1: Enable Apple Sign In
Toggle Enable Sign in with Apple to ON. This activates Apple as an authentication provider in your Supabase project.
4
Step 3: Configure Apple Developer Identifiers
In Apple Developer Portal, go to Certificates, Identifiers & Profiles:
- Select Identifiers → Your App ID
- Ensure Sign in with Apple capability is checked
- Click Save
5
Step 4: Complete Apple Developer Portal Setup
Complete the Apple Developer Portal configuration:
- Services ID: Create one if needed for web callback
- Team ID: Your Apple Developer Team ID
- Key ID: Generate a new key with Sign in with Apple enabled
- Private Key: Download and save securely
6
Step 5: Add Xcode Capability
In Xcode, go to your target’s Signing & Capabilities:
- Click + Capability
- Search for “Sign in with Apple”
- Add it to your target
Apple requires apps that offer third-party login (like Google) to also support Sign in with Apple. The boilerplate has this pre-built with Supabase integration.
Google Sign In Setup
Enable Google:- Click Google in Supabase Providers
- Toggle Enable Sign in with Google
- Configure:
- Client ID (for OAuth): From Google Cloud Console
- Client Secret: From Google Cloud Console
- Add authorized redirect URIs:
- Click Save
2. Configure iOS App
Update Secrets Configuration:Package.swift:
3. Setup CompositionRoot
The boilerplate comes with auth pre-configured, but here’s how it works:Usage
Sign In Flow
TheSignInView provides a premium, minimal authentication experience:
- Clean, Apple-like aesthetic with generous whitespace
- Native Apple button (HIG compliant) as primary CTA
- Visual hierarchy: Apple → Google → “Use email instead” link
- Premium feel with continuous corner radii and subtle borders
- Adapts to light/dark mode automatically
- Apple Sign In: Native button (HIG compliant) - primary option
- Google Sign In: Secondary button with subtle border
- Email Sign In: Shown via “Use email instead” link (opens sheet)
- Create Account: Accessible from email login sheet
- Forgot Password: Accessible from email login sheet
- Links and accents use
DSColors.accentPrimary(warm pink in Aurora, neutral in others) - Text colors use
DSColors.textPrimaryandDSColors.textSecondary - Backgrounds and surfaces adapt to theme palette
- Icons inherit theme accent color
- No hardcoded system blue - everything theme-aware
SwiftAIBoilerplatePro/AppShell/SignInView.swift:
Spacing & Rhythm:
- Top space:
Spacer().frame(height: 100)- Adjust for vertical positioning - Between hero and buttons:
64pt- Control breathing room - Bottom space:
80ptthen48pt- Legal section padding
- App title:
28pt semibold rounded- Adjust size/weight - Tagline:
15pt regular, 0.3 tracking, 70% opacity- Refine elegance - Legal text:
12pt, 55% opacity- Keep whisper-quiet
- Avatar blur:
blur(radius: 20)on gradient circle - Background: Subtle top-to-bottom gradient
- Google button:
surface.opacity(0.6)with0.5pt border - Link colors: Uses
accentPrimary.opacity(0.7)for cohesion
- Hero fade-in:
.easeOut(duration: 0.6)on appear - Buttons slide:
.delay(0.15)for staggered entrance - Error message:
.spring(response: 0.35)for smooth entry
- Max width:
380ptfor button container (narrower = more refined)
Check Authentication State
Sign Out
- Revoke the access token on the server
- Clear tokens from Keychain
- Clear in-memory session
- Navigate to sign-in screen
How It Works
Apple Sign In Flow
- User taps “Continue with Apple”
- System shows Apple Sign In sheet
- User authenticates with Face ID/Touch ID
- App receives Apple ID token + nonce
- Token is exchanged with Supabase for session
- Session stored in Keychain
- User navigated to main screen
Google Sign In Flow
- User taps “Continue with Google”
- Google Sign In SDK presents OAuth flow
- User selects Google account
- App receives Google ID token
- Token is exchanged with Supabase for session
- Session stored in Keychain
- User navigated to main screen
Email Sign In Flow
- User enters email and password
- Credentials sent to Supabase
- Supabase validates and returns session
- Session stored in Keychain
- User navigated to main screen
Session Persistence Details
How Sessions Are Stored
Sessions are stored in iOS Keychain with the following keys:- Uses
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly - Data is encrypted by iOS
- Survives app updates
- Deleted on app uninstall
Automatic Session Loading
On app launch (loadInitialSession()):
- Load from Keychain: Attempts to load stored session
- Validate Expiry: Checks if access token is expired
- Attempt Refresh: If expired, tries to refresh using the refresh token (up to 3 attempts)
- Recover or Clear: Restores session if refresh succeeds, clears if refresh token is also expired
- Emit State: Notifies observers of auth state (
.refreshingduring recovery)
Token Refresh Strategy
The app uses proactive refresh and reactive recovery to ensure users stay logged in: Proactive Refresh (Before Expiry):- Schedule Refresh: 60 seconds before token expiry
- Silent Background Execution: User never sees a loading state
- Token Rotation: Handles Supabase refresh token rotation
- Detect Expired Session: On app launch, check if access token expired
- Attempt Refresh: Use refresh token to get new access token
- Retry Logic: Up to 3 attempts with exponential backoff
- Emit
.refreshingState: Show loading UI if needed
Result: Users stay logged in for days (until refresh token expires), not just 1 hour (access token lifetime).
Navigation Based on Auth State
TheLaunchRouter automatically handles navigation:
- ✅ Users automatically navigate to main screen when signed in
- ✅ Users automatically navigate to sign in when signed out
- ✅ No manual navigation needed
- ✅ Works for all auth methods (Apple, Google, Email)
Best Practices
Always Check Auth State
Handle Sign Out Gracefully
Use Session Tokens for API Calls
The Networking package automatically includes auth tokens:Troubleshooting
Users Have to Sign In Every Time
This should be rare with the new session recovery. Check:- Keychain is accessible (not disabled in Xcode capabilities)
loadInitialSession()is being called- No errors in
SessionManagerinitialization - Check logs for refresh attempts and failures
- Verify refresh token hasn’t expired (7+ days of inactivity)
With proper session recovery, users only need to sign in again if their refresh token expires (typically 7+ days of not opening the app).
Google Sign In Not Working
- Verify
GOOGLE_CLIENT_IDis set inSecrets.xcconfig - Check Google Cloud Console configuration
- Ensure redirect URIs match exactly
- Verify GoogleSignIn SDK is installed
Apple Sign In Fails
- Supabase Configuration: Verify Apple provider is enabled in Supabase Authentication → Providers
- Apple Developer Portal: Check that Sign in with Apple capability is enabled on your App ID
- Xcode Capability: Ensure “Sign in with Apple” capability is added in Signing & Capabilities
- Credentials: Verify Team ID, Key ID, and Private Key are correct in Supabase
- Bundle ID: Check bundle ID matches between Xcode, App Store Connect, and Supabase
Token Refresh Fails
Check logs for:- Network connectivity issues
- Supabase service status
- Invalid refresh token (forces re-authentication)
- Too many concurrent refresh attempts
Security Considerations
- Tokens in Keychain: Never store tokens in UserDefaults or files
- HTTPS Only: All auth requests use HTTPS
- Token Expiry: Access tokens expire (default: 1 hour), but sessions persist via refresh tokens
- Refresh Token Lifetime: Configurable in Supabase dashboard (default: 7+ days)
- Refresh Rotation: Supabase rotates refresh tokens for security
- Server-Side Validation: Always validate tokens server-side
- Detailed Logging: Auth events are logged for debugging (tokens are never logged)
