Skip to main content

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_URL set in apps/mobile/.env (from apps/mobile/example.env)

Steps

  1. Configure auth providers in the API: Backend Authentication Setup
  2. Verify mobile auth screens in apps/mobile/app/auth
  3. 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 in lib/auth/client.ts:
Key Features:
  • 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
Google OAuth (Android) requires a single origin.If your API is exposed via ngrok (e.g. https://xxxx.ngrok-free.app), then:
  • BETTER_AUTH_URL (API) must use that same origin
  • EXPO_PUBLIC_API_URL (mobile) must also use that same origin
If mobile starts auth at http://192.168.x.x:3001 but the callback returns to https://xxxx.ngrok-free.app, you will get a state mismatch error.

2. Route Protection

Authentication state determines which screens users can access. The current implementation handles redirects in useAppNavigation.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: SessionProvider calls authClient.getSession() on mount and exposes a refetch() helper used after sign-in/sign-out
  • Navigation: useAppNavigation derives the auth/onboarding target route

4. Device Information Tracking

Every authentication request includes device metadata:
Use Cases:
  • 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:
Features:
  • 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 calls authClient.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-authentication flow to obtain an Apple identity token and then calls Better Auth signIn.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 the launch:// 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

Cause: SecureStore permissions or configuration issueSolution:
  1. Check that expo-secure-store is properly installed
  2. Verify the storage prefix matches your app configuration
  3. Test on a physical device (simulator may have limitations)
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)
Cause: Component not subscribed to auth state changesSolution:
  1. Use authClient.useSession() hook in your components
  2. Ensure components are wrapped in proper providers
  3. 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