Overview
The Launch mobile app uses Better Auth with Expo integration for a secure, seamless authentication experience. This guide explains how authentication works in the mobile client and how it connects to the API.Prerequisites
- Backend running with auth routes enabled
EXPO_PUBLIC_API_URLset inapps/mobile/.env(fromapps/mobile/example.env)
Steps
- Configure auth providers in the API: Backend Authentication Setup
- Verify mobile auth screens in
apps/mobile/app/auth - Test sign‑in on device or simulator
Architecture
Authentication Flow
Key Components
Auth Client
Location:
apps/mobile/lib/auth/client.ts. Central authentication client
that handles Better Auth requests, secure storage, and device headers.Route Protection
Location:
app/_layout.tsx and lib/hooks/useAppNavigation.ts. Navigation
guards redirect users based on session and onboarding state.Device Tracking
Location:
apps/mobile/lib/utils/device-info.ts. Captures device
information for security and analytics purposes.Implementation Details
1. Auth Client Setup
The authentication client is configured inlib/auth/client.ts:
- Secure Storage: Uses Expo SecureStore for session persistence
- Device Headers: Automatically includes device information in all requests
- Deep Linking: Handles OAuth callbacks via
launch://scheme - Type Safety: Full TypeScript support with session hooks
2. Route Protection
Authentication state determines which screens users can access. The current implementation handles redirects inuseAppNavigation.ts and keeps the route
stack defined in app/_layout.tsx.
Benefits:
- Centralized: Redirect rules live in one hook
- Automatic: Users are routed based on auth and onboarding state
- Type Safe: Expo Router provides full TypeScript support
3. Session Management
Sessions are managed by a lightweight provider that calls Better Auth to fetch the current session on app start and after auth events:- Persistence: Sessions survive app restarts via SecureStore
- Manual refresh:
SessionProvidercallsauthClient.getSession()on mount and exposes arefetch()helper used after sign-in/sign-out - Navigation:
useAppNavigationderives the auth/onboarding target route
4. Device Information Tracking
Every authentication request includes device metadata:- Security: Detect suspicious login patterns
- Analytics: Understand user device distribution
- Support: Debug issues specific to device types
- Features: Enable/disable features based on device capabilities
Authentication Providers
Apple Sign-In
Configured for iOS devices with automatic availability detection:- Native UI: Uses Apple’s native sign-in button
- Secure: Implements proper nonce generation for security
- Graceful Fallback: Shows standard button when unavailable
Google Sign-In
Implemented via Better Auth’s Expo client. The login screen callsauthClient.signIn.social({ provider: "google" }), which opens the OAuth flow
in a browser and returns to the app via the launch:// scheme.
Email Sign-In (OTP)
Email OTP sign-in is wired end-to-end. The flow uses Better Auth’s email OTP plugin and a dedicated verification screen:apps/mobile/app/auth/email-signin.tsx(send code)apps/mobile/app/auth/verify-email-otp.tsx(enter code)docs/authentication/email-signin.mdx(setup details)
Platform-specific Behavior
iOS
- Apple Sign-In uses the native
expo-apple-authenticationflow to obtain an Apple identity token and then calls Better AuthsignIn.social({ provider: "apple", idToken }). - Google Sign-In uses Better Auth’s Expo client for browser-based OAuth and
deep links back to the app via the
launch://scheme.
Android
- Google Sign-In uses the same Better Auth Expo client flow as iOS (browser OAuth + deep link). Ensure your auth flow starts and ends on the same origin to avoid state mismatch errors.
- Apple Sign-In is not available on Android.
Security Notes
Sessions are stored in SecureStore, OAuth redirects use thelaunch:// scheme,
and device metadata is attached to auth requests for tracing and support.
Next Steps
- Apple Sign-In Setup
- Google Sign-In Setup
- Email Sign-In with OTP
- CORS Protection: Configured trusted origins prevent unauthorized access
- Request Signing: Device headers provide request authenticity
- Rate Limiting: Backend prevents brute force attacks
- Error Logging: Comprehensive error tracking for security monitoring
Usage Examples
Checking Authentication State
Manual Sign Out
Accessing User Data
Troubleshooting
Common Issues
Session not persisting across app restarts
Session not persisting across app restarts
Cause: SecureStore permissions or configuration issueSolution:
- Check that
expo-secure-storeis properly installed - Verify the storage prefix matches your app configuration
- Test on a physical device (simulator may have limitations)
Apple Sign-In not working
Apple Sign-In not working
Cause: Missing Apple Developer configuration Solution: 1. Ensure
usesAppleSignIn: true in app.config.ts 2. Add Apple Sign-In capability in
Xcode 3. Configure Apple App ID with Sign-In capability 4. Set up proper
environment variables (see Environment Setup)Auth state not updating UI
Auth state not updating UI
Cause: Component not subscribed to auth state changesSolution:
- Use
authClient.useSession()hook in your components - Ensure components are wrapped in proper providers
- Check that React Query is configured correctly
Debug Mode
Enable detailed auth logging by setting:Environment Variables
The following environment variables are required in your API backend:Next Steps
See the Environment Setup Guide for complete configuration details.Next Steps
- Environment Setup - Configure your development environment
- File Structure - Understand the mobile app organization