> ## Documentation Index
> Fetch the complete documentation index at: https://docs.launchtoday.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Mobile Authentication

> Complete guide to authentication implementation in the mobile app

## Overview

The Launch mobile app uses [Better Auth](https://better-auth.com) 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](/authentication/backend-setup)
2. Verify mobile auth screens in `apps/mobile/app/auth`
3. Test sign‑in on device or simulator

## Architecture

### Authentication Flow

```mermaid theme={null}
graph LR
    A[User Opens App] --> B{Session Check}
    B -->|No Session| C[Landing Page]
    B -->|Valid Session| D[Protected App]
    C --> E[Login Screen]
    E --> F[Social/Email Auth]
    F --> G[Better Auth API]
    G --> H[Session Created]
    H --> D
```

### Key Components

<Card title="Auth Client" icon="key">
  **Location**: `apps/mobile/lib/auth/client.ts`. Central authentication client
  that handles Better Auth requests, secure storage, and device headers.
</Card>

<Card title="Route Protection" icon="shield">
  **Location**: `app/_layout.tsx` and `lib/hooks/useAppNavigation.ts`. Navigation
  guards redirect users based on session and onboarding state.
</Card>

<Card title="Device Tracking" icon="mobile">
  **Location**: `apps/mobile/lib/utils/device-info.ts`. Captures device
  information for security and analytics purposes.
</Card>

## Implementation Details

### 1. Auth Client Setup

The authentication client is configured in `lib/auth/client.ts`:

```typescript theme={null}
export const authClient = createAuthClient({
  // IMPORTANT: For mobile OAuth (Google), this must be reachable from your device.
  // Use your ngrok HTTPS URL during development (recommended).
  baseURL: `${process.env.EXPO_PUBLIC_API_URL}/api/auth`,
  plugins: [
    expoClient({
      scheme: "launch", // Deep link scheme
      storagePrefix: "launch", // SecureStore prefix
      storage: SecureStore, // Native secure storage
    }),
  ],
  fetchOptions: {
    customFetchImpl: async (url, init) => {
      const deviceHeaders = getDeviceHeaders();
      // Automatically inject device info in all requests
      return fetch(url, {
        ...init,
        headers: { ...init?.headers, ...deviceHeaders },
        credentials: "omit",
      });
    },
  },
});
```

**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

<Warning>
  **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.
</Warning>

### 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:

```typescript theme={null}
export const getDeviceHeaders = (): Record<string, string> => {
  const deviceInfo = getDeviceInfo();

  return {
    "X-Device-Name": deviceInfo.deviceName || "unknown",
    "X-Device-Model": deviceInfo.deviceModel || "unknown",
    "X-OS-Version": deviceInfo.osVersion || "unknown",
    "X-App-Version": deviceInfo.appVersion || "unknown",
    "X-App-Platform": deviceInfo.platform,
    "X-Device-Type": deviceInfo.deviceType,
  };
};
```

**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:

```typescript theme={null}
// Check if Apple Sign-In is available
const isAvailable = await AppleAuthentication.isAvailableAsync();

// Handle Apple authentication
await authClient.signIn.social({
  provider: "apple",
  idToken: {
    token: credential.identityToken,
    nonce,
  },
  callbackURL: "/",
});
```

**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](/authentication/apple-signin)

* [Google Sign-In Setup](/authentication/google-signin)

* [Email Sign-In with OTP](/authentication/email-signin)

* **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

```typescript theme={null}
import { authClient } from "@/lib/auth-client";

function MyComponent() {
  const { data: session, isPending } = authClient.useSession();

  if (isPending) return <LoadingSpinner />;

  if (session) {
    return <WelcomeMessage user={session.user} />;
  }

  return <LoginPrompt />;
}
```

### Manual Sign Out

```typescript theme={null}
const handleSignOut = async () => {
  try {
    await authClient.signOut();
    // User automatically redirected to public routes
  } catch (error) {
    console.error("Sign out error:", error);
  }
};
```

### Accessing User Data

```typescript theme={null}
const { data: session } = authClient.useSession();

if (session?.user) {
  const { name, email, image } = session.user;
  // Use user data in your components
}
```

## Troubleshooting

### Common Issues

<AccordionGroup>
  <Accordion title="Session not persisting across app restarts">
    **Cause**: SecureStore permissions or configuration issue

    **Solution**:

    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)
  </Accordion>

  <Accordion title="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)
  </Accordion>

  <Accordion title="Auth state not updating UI">
    **Cause**: Component not subscribed to auth state changes

    **Solution**:

    1. Use `authClient.useSession()` hook in your components
    2. Ensure components are wrapped in proper providers
    3. Check that React Query is configured correctly
  </Accordion>
</AccordionGroup>

### Debug Mode

Enable detailed auth logging by setting:

```typescript theme={null}
// In development
if (__DEV__) {
  console.log("Auth Debug Mode Enabled");
  // Additional logging will appear in console
}
```

## Environment Variables

The following environment variables are required in your API backend:

```bash theme={null}
# Better Auth Configuration
BETTER_AUTH_SECRET=your-secret-key
BETTER_AUTH_URL=http://localhost:3001

# Apple Sign-In (iOS)
APPLE_CLIENT_ID=your.app.bundle.id
APPLE_TEAM_ID=YOUR_TEAM_ID
APPLE_KEY_ID=YOUR_KEY_ID
APPLE_PRIVATE_KEY_BASE64=base64_encoded_private_key

# Database
DATABASE_URL=postgresql://user:password@localhost:5432/launch
```

## Next Steps

* [Apple Sign-In](/authentication/apple-signin)
* [Google Sign-In](/authentication/google-signin)

See the [Environment Setup Guide](/mobile/environment-setup) for complete configuration details.

## Next Steps

* [Environment Setup](/mobile/environment-setup) - Configure your development environment
* [File Structure](/mobile/file-structure) - Understand the mobile app organization
