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

# Social Login

> Google and Apple Sign-In setup for Shipnative

Shipnative supports Google and Apple Sign-In with both Supabase and Convex backends. The implementation uses different strategies per platform for optimal user experience.

## How It Works

<Tabs>
  <Tab title="Supabase">
    | Provider   | iOS/Android                    | Web                           |
    | ---------- | ------------------------------ | ----------------------------- |
    | **Google** | Native SDK (ID token exchange) | OAuth PKCE (browser redirect) |
    | **Apple**  | OAuth PKCE via in-app browser  | OAuth PKCE (browser redirect) |

    **Google on mobile** uses `@react-native-google-signin/google-signin` to get an ID token directly, then exchanges it with Supabase. No browser redirect needed.

    **Apple on mobile** uses OAuth PKCE flow with `expo-web-browser`, which opens an in-app browser for authentication.

    **Web OAuth** redirects the browser to the OAuth provider (Google/Apple), then back to `/auth/callback` where the `AuthCallbackScreen` handles the token exchange automatically.
  </Tab>

  <Tab title="Convex">
    | Provider   | iOS/Android                   | Web                           |
    | ---------- | ----------------------------- | ----------------------------- |
    | **Google** | OAuth PKCE via in-app browser | OAuth PKCE (browser redirect) |
    | **Apple**  | OAuth PKCE via in-app browser | OAuth PKCE (browser redirect) |
    | **GitHub** | OAuth PKCE via in-app browser | OAuth PKCE (browser redirect) |

    **All providers on mobile** use OAuth PKCE flow with `expo-web-browser`. Convex Auth doesn't support native ID token verification, so all OAuth flows go through the browser.

    **Web OAuth** redirects the browser to the OAuth provider, then back to your app where the session is established automatically.

    <Warning>
      **Mobile OAuth requires a deployed Convex backend.** OAuth flows on iOS/Android simulators cannot work with local Convex (`127.0.0.1`) because OAuth providers can't redirect back to localhost. See [Mobile OAuth Requirements](#mobile-oauth-requirements-convex) below.
    </Warning>
  </Tab>
</Tabs>

***

## Quick Start

<Tabs>
  <Tab title="Supabase">
    ```typescript theme={null}
    import { useSupabaseAuth } from '@/hooks/supabase'

    function LoginScreen() {
      const { signInWithGoogle, signInWithApple } = useSupabaseAuth()

      const handleGoogle = async () => {
        const { error } = await signInWithGoogle()
        if (error && error.message !== 'OAuth flow cancelled') {
          alert(error.message)
        }
      }

      const handleApple = async () => {
        const { error } = await signInWithApple()
        if (error && error.message !== 'OAuth flow cancelled') {
          alert(error.message)
        }
      }

      return (
        <View>
          <Button onPress={handleGoogle} title="Continue with Google" />
          <Button onPress={handleApple} title="Continue with Apple" />
        </View>
      )
    }
    ```
  </Tab>

  <Tab title="Convex">
    ```typescript theme={null}
    import { useConvexAuth } from '@/hooks/convex'

    function LoginScreen() {
      const { signInWithGoogle, signInWithApple } = useConvexAuth()

      const handleGoogle = async () => {
        const { error } = await signInWithGoogle()
        if (error && error.message !== 'OAuth flow cancelled') {
          alert(error.message)
        }
      }

      const handleApple = async () => {
        const { error } = await signInWithApple()
        if (error && error.message !== 'OAuth flow cancelled') {
          alert(error.message)
        }
      }

      return (
        <View>
          <Button onPress={handleGoogle} title="Continue with Google" />
          <Button onPress={handleApple} title="Continue with Apple" />
        </View>
      )
    }
    ```
  </Tab>
</Tabs>

***

## Google Sign-In Setup

<Tabs>
  <Tab title="Supabase">
    ### 1. Create OAuth Credentials

    In [Google Cloud Console](https://console.cloud.google.com/apis/credentials):

    1. Create or select a project
    2. Go to **APIs & Services** → **OAuth consent screen**
       * Configure app name, support email, scopes (`openid`, `email`, `profile`)
    3. Go to **APIs & Services** → **Credentials** → **Create Credentials** → **OAuth client ID**
    4. Create three client IDs:
       * **Web application** - Copy the Client ID and Client Secret
       * **iOS** - Use your bundle identifier
       * **Android** - Use your package name and SHA-1 fingerprint

    ### 2. Configure Supabase

    In **Supabase Dashboard** → **Authentication** → **Providers** → **Google**:

    1. Enable Google provider
    2. Add the **Client Secret** (from Web client)
    3. Add **all Client IDs** (Web first, then iOS and Android) separated by commas
    4. Enable **Skip nonce check** - Required because the React Native Google Sign-In SDK doesn't support nonce verification

    ### 3. Configure Your App

    Add to `apps/app/.env`:

    ```bash theme={null}
    EXPO_PUBLIC_GOOGLE_CLIENT_ID=your-web-client-id.apps.googleusercontent.com
    EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=your-ios-client-id.apps.googleusercontent.com
    ```

    ### 4. Add Redirect URL

    In **Supabase Dashboard** → **Authentication** → **URL Configuration** → **Redirect URLs**, add:

    * `yourappscheme://auth/callback` (your app scheme from `app.json`)
    * `http://localhost:19006/auth/callback` (local web development)
  </Tab>

  <Tab title="Convex">
    ### 1. Create OAuth Credentials

    In [Google Cloud Console](https://console.cloud.google.com/apis/credentials):

    1. Create or select a project
    2. Go to **APIs & Services** → **OAuth consent screen**
       * Configure app name, support email, scopes (`openid`, `email`, `profile`)
    3. Go to **APIs & Services** → **Credentials** → **Create Credentials** → **OAuth client ID**
    4. Create client IDs for each platform you need

    ### 2. Configure Convex Auth

    In `convex/auth.ts`:

    ```typescript theme={null}
    import Google from "@auth/core/providers/google"

    export default {
      providers: [
        Google({
          clientId: process.env.AUTH_GOOGLE_ID,
          clientSecret: process.env.AUTH_GOOGLE_SECRET,
        }),
      ],
    }
    ```

    ### 3. Set Environment Variables

    In the Convex Dashboard, add environment variables:

    * `AUTH_GOOGLE_ID` - Your Google Client ID
    * `AUTH_GOOGLE_SECRET` - Your Google Client Secret

    ### 4. Configure Your App

    Add to `apps/app/.env`:

    ```bash theme={null}
    EXPO_PUBLIC_GOOGLE_CLIENT_ID=your-web-client-id.apps.googleusercontent.com
    EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=your-ios-client-id.apps.googleusercontent.com
    ```
  </Tab>
</Tabs>

### Rebuild Dev Client

After adding Google Sign-In, rebuild your development client:

```bash theme={null}
npx expo prebuild --clean
yarn ios  # or yarn android
```

***

## Apple Sign-In Setup

<Tabs>
  <Tab title="Supabase">
    ### 1. Configure App ID

    In [Apple Developer Portal](https://developer.apple.com/account/resources/identifiers/list):

    1. Go to **Certificates, Identifiers & Profiles** → **Identifiers**
    2. Select your App ID (or create one)
    3. Enable **Sign In with Apple** capability
    4. Save

    ### 2. Create Services ID (for OAuth)

    1. Go to **Identifiers** → Click **+**
    2. Select **Services IDs** → Continue
    3. Set identifier (e.g., `com.yourcompany.yourapp.signin`)
    4. Enable **Sign In with Apple**
    5. Click **Configure**:
       * Primary App ID: Select your main app
       * Domains: Add your Supabase domain (e.g., `your-project.supabase.co`)
       * Return URLs: Add `https://your-project.supabase.co/auth/v1/callback`
    6. Save

    ### 3. Generate Private Key

    1. Go to **Keys** → Click **+**
    2. Name it (e.g., "Supabase Auth Key")
    3. Enable **Sign In with Apple**
    4. Click **Configure** → Select your Primary App ID
    5. Register the key
    6. Download the `.p8` file (you can only download once!)
    7. Note the **Key ID**

    ### 4. Configure Supabase

    In **Supabase Dashboard** → **Authentication** → **Providers** → **Apple**:

    1. Enable Apple provider
    2. Enter your **Services ID** (e.g., `com.yourcompany.yourapp.signin`)
    3. Enter your **Team ID** (found in Apple Developer account)
    4. Enter your **Key ID**
    5. Paste the **Private Key** content (entire `.p8` file including headers)

    The private key stays in Supabase Dashboard - it should never be in your app or `.env` file.
  </Tab>

  <Tab title="Convex">
    ### 1. Configure App ID

    In [Apple Developer Portal](https://developer.apple.com/account/resources/identifiers/list):

    1. Go to **Certificates, Identifiers & Profiles** → **Identifiers**
    2. Select your App ID (or create one)
    3. Enable **Sign In with Apple** capability
    4. Save

    ### 2. Create Services ID

    1. Go to **Identifiers** → Click **+**
    2. Select **Services IDs** → Continue
    3. Set identifier (e.g., `com.yourcompany.yourapp.signin`)
    4. Enable **Sign In with Apple**
    5. Click **Configure** with your Convex deployment domain
    6. Save

    ### 3. Generate Private Key

    Same as Supabase - download the `.p8` file and note the Key ID.

    ### 4. Configure Convex Auth

    In `convex/auth.ts`:

    ```typescript theme={null}
    import Apple from "@auth/core/providers/apple"

    export default {
      providers: [
        Apple({
          clientId: process.env.AUTH_APPLE_ID,
          clientSecret: process.env.AUTH_APPLE_SECRET,
        }),
      ],
    }
    ```

    Set environment variables in the Convex Dashboard:

    * `AUTH_APPLE_ID` - Your Services ID
    * `AUTH_APPLE_SECRET` - Generated JWT (see [Auth.js Apple docs](https://authjs.dev/getting-started/providers/apple))
  </Tab>
</Tabs>

***

## Mobile OAuth Requirements (Convex)

<Warning>
  This section applies only to **Convex** backends. Supabase OAuth works with local development.
</Warning>

### Why Mobile OAuth Requires Deployment

When using Convex Auth with OAuth providers (Google, Apple, GitHub), the authentication flow works like this:

```mermaid theme={null}
sequenceDiagram
    participant App as Mobile App
    participant Convex as Convex Site (SITE_URL)
    participant Google as OAuth Provider

    App->>Convex: Start OAuth flow
    Convex->>Google: Redirect to authorization
    Google->>Google: User authenticates
    Google->>Convex: Callback with auth code
    Convex->>App: Redirect to app with session
```

The OAuth provider (Google/Apple/GitHub) redirects to your **Convex site URL** (`SITE_URL`), not directly to your app. This means:

* **`SITE_URL` must be publicly accessible** - OAuth providers cannot redirect to `localhost` or `127.0.0.1`
* **Mobile simulators can't reach localhost** - Even if the OAuth flow started, the final redirect back to your app would fail

### Environment Variables Required

Set these in the **Convex Dashboard** → **Settings** → **Environment Variables**:

| Variable             | Description                                 | Example                             |
| -------------------- | ------------------------------------------- | ----------------------------------- |
| `SITE_URL`           | Your Convex deployment URL (must be public) | `https://your-project.convex.site`  |
| `AUTH_GOOGLE_ID`     | Google OAuth Client ID                      | `123456.apps.googleusercontent.com` |
| `AUTH_GOOGLE_SECRET` | Google OAuth Client Secret                  | `GOCSPX-xxxxx`                      |
| `AUTH_APPLE_ID`      | Apple Services ID                           | `com.yourapp.signin`                |
| `AUTH_APPLE_SECRET`  | Apple Client Secret (JWT)                   | `eyJhbGc...`                        |
| `AUTH_GITHUB_ID`     | GitHub OAuth App Client ID                  | `Iv1.abc123`                        |
| `AUTH_GITHUB_SECRET` | GitHub OAuth App Client Secret              | `ghp_xxxxx`                         |

<Tip>
  You can check your current environment variables with:

  ```bash theme={null}
  npx convex env list
  ```
</Tip>

### Development Options

<AccordionGroup>
  <Accordion title="Option 1: Deploy to Convex Cloud (Recommended)">
    The simplest approach is to use a cloud Convex deployment for OAuth testing:

    ```bash theme={null}
    # Deploy your Convex functions to the cloud
    npx convex deploy

    # Get your deployment URL (shown in output)
    # It will be something like: https://your-project-123.convex.cloud

    # Set SITE_URL to your Convex site URL
    npx convex env set SITE_URL "https://your-project-123.convex.site"
    ```

    Then update your app's `.env`:

    ```bash theme={null}
    EXPO_PUBLIC_CONVEX_URL=https://your-project-123.convex.cloud
    ```

    <Info>
      Your Convex site URL (ending in `.convex.site`) is different from your Convex cloud URL (ending in `.convex.cloud`). Use the `.convex.site` URL for `SITE_URL`.
    </Info>
  </Accordion>

  <Accordion title="Option 2: Use ngrok for Local Development">
    If you want to test OAuth with your local Convex backend:

    1. **Start your local Convex dev server:**
       ```bash theme={null}
       npx convex dev
       ```

    2. **In another terminal, start ngrok:**

       ```bash theme={null}
       ngrok http 3211
       ```

       This gives you a public URL like `https://abc123.ngrok.io`

    3. **Set SITE\_URL to the ngrok URL:**
       ```bash theme={null}
       npx convex env set SITE_URL "https://abc123.ngrok.io"
       ```

    4. **Update OAuth provider redirect URLs** to include your ngrok URL

    <Warning>
      ngrok URLs change each time you restart. You'll need to update `SITE_URL` and your OAuth provider settings each session. For consistent development, use Option 1.
    </Warning>
  </Accordion>

  <Accordion title="Option 3: Test OAuth on Web Only">
    During local development, OAuth works on web but not mobile:

    ```bash theme={null}
    # Run the web version
    cd apps/app && yarn web
    ```

    Web OAuth works because:

    * The browser can follow redirects to `localhost`
    * Cookies are preserved through the OAuth flow
    * No native app scheme is required

    Use this approach to test OAuth logic, then deploy to cloud for mobile testing.
  </Accordion>
</AccordionGroup>

### Configure OAuth Provider Redirect URLs

After setting up your Convex deployment, add these redirect URLs to your OAuth providers:

**Google Cloud Console:**

* Authorized redirect URIs: `https://your-project.convex.site/api/auth/callback/google`

**Apple Developer Portal:**

* Return URLs: `https://your-project.convex.site/api/auth/callback/apple`

**GitHub OAuth App:**

* Authorization callback URL: `https://your-project.convex.site/api/auth/callback/github`

### Deep Link Configuration

Your app needs to handle the final redirect from Convex. Ensure your `app.json` has the correct scheme:

```json theme={null}
{
  "expo": {
    "scheme": "shipnative"
  }
}
```

<Info>
  **Dev vs Production URL schemes:**

  Expo development builds use `exp+<scheme>://` as the URL scheme, while production builds use `<scheme>://`. Your Convex auth config should allow both.
</Info>

The Convex Auth redirect callback in `convex/auth.ts` validates these URLs:

```typescript theme={null}
callbacks: {
  async redirect({ redirectTo }) {
    // Allow your app's deep link scheme (production builds)
    if (redirectTo?.startsWith("shipnative://")) {
      return redirectTo
    }
    // Allow Expo development builds (exp+scheme://)
    if (redirectTo?.startsWith("exp+shipnative://")) {
      return redirectTo
    }
    // Allow Expo Go URLs
    if (redirectTo?.startsWith("exp://")) {
      return redirectTo
    }
    // Default fallback for mobile
    return "shipnative://"
  },
}
```

***

## Web OAuth Setup

<Info>
  Web OAuth works automatically with Shipnative! Just ensure your redirect URLs are configured correctly.
</Info>

When running on web, OAuth providers redirect the browser directly. Shipnative handles this via the `AuthCallbackScreen` component which:

1. Extracts tokens from the URL hash fragment (`#access_token=...&refresh_token=...`)
2. Exchanges them for a session with Supabase
3. Redirects to the authenticated area of your app

### Required Configuration

<Tabs>
  <Tab title="Supabase">
    Add these redirect URLs in **Supabase Dashboard** → **Authentication** → **URL Configuration** → **Redirect URLs**:

    ```bash theme={null}
    # Local development
    http://localhost:19006/auth/callback

    # Production (replace with your domain)
    https://yourapp.com/auth/callback
    ```
  </Tab>

  <Tab title="Convex">
    Configure redirect URLs in your Convex auth configuration and ensure your deployment URL is set up correctly in the Convex Dashboard.
  </Tab>
</Tabs>

### Google Cloud Console (Web Client)

For Google OAuth on web, ensure your **Web application** OAuth client has:

1. **Authorized JavaScript origins**:
   * `http://localhost:19006` (development)
   * `https://yourapp.com` (production)

2. **Authorized redirect URIs**:
   * Your Supabase callback URL: `https://your-project.supabase.co/auth/v1/callback`

### How It Works Technically

```mermaid theme={null}
sequenceDiagram
    participant User
    participant App
    participant Supabase
    participant Google

    User->>App: Clicks "Sign in with Google"
    App->>Supabase: signInWithOAuth({ provider: 'google' })
    Supabase-->>App: Returns OAuth URL
    App->>Google: Browser redirects to Google
    User->>Google: Authenticates
    Google->>App: Redirects to /auth/callback#access_token=...
    App->>App: AuthCallbackScreen extracts tokens
    App->>Supabase: setSession() or detectSessionInUrl
    Supabase-->>App: Session established
    App->>User: Navigates to authenticated app
```

***

## Troubleshooting

### General Issues

**"Google Sign-In is not available on this platform"**

* Ensure `@react-native-google-signin/google-signin` is installed
* Rebuild your dev client after adding native modules

**"Google ID token not returned"**

* Check that `EXPO_PUBLIC_GOOGLE_CLIENT_ID` is set correctly
* Verify the Web Client ID matches what's in Google Cloud Console

**Apple Sign-In button doesn't appear on Android**

* Apple Sign-In is iOS and Web only. Hide the button on Android:
  ```typescript theme={null}
  {Platform.OS !== 'android' && <AppleSignInButton />}
  ```

**OAuth redirects to wrong place**

* Verify redirect URLs match your app scheme
* Check backend configuration for correct callback URLs

### Supabase-Specific

**"Nonce mismatch" errors**

* Enable **Skip nonce check** in Supabase Google provider settings

**Web OAuth shows "Invalid params" error**

* Ensure your redirect URL in Supabase includes `/auth/callback`
* Check that `detectSessionInUrl: true` is set in the Supabase client config (default in Shipnative)
* Verify your domain is in the allowed redirect URLs in Supabase Dashboard

**Web OAuth redirects but doesn't log in**

* Check browser console for CORS errors
* Add your domain to Supabase's allowed origins (Dashboard → Project Settings → API)
* Ensure tokens aren't being stripped by your hosting provider's redirects

### Convex-Specific

**Mobile OAuth shows "Convex Auth is running" page instead of OAuth provider**

This happens when `SITE_URL` is set to `localhost` or `127.0.0.1`. The OAuth flow is trying to use your local Convex server, which mobile devices can't access.

**Fix:**

```bash theme={null}
# Check current SITE_URL
npx convex env list

# If it shows 127.0.0.1, you need to deploy
npx convex deploy

# Then set SITE_URL to your deployed URL
npx convex env set SITE_URL "https://your-project.convex.site"
```

**OAuth opens WebView but immediately closes or fails**

* Check that `expo-web-browser` is installed: `npx expo install expo-web-browser`
* Verify the OAuth provider credentials are set in Convex Dashboard
* Check Convex function logs for errors: `npx convex logs`

**"Invalid redirectTo URI" error in Convex logs**

Your app is sending a redirect URI that isn't allowed. Update `convex/auth.ts`:

```typescript theme={null}
callbacks: {
  async redirect({ redirectTo }) {
    // Add your allowed schemes
    if (redirectTo?.startsWith("yourappscheme://")) {
      return redirectTo
    }
    if (redirectTo?.startsWith("exp://")) {
      return redirectTo
    }
    return "yourappscheme://"
  },
}
```

**OAuth works on web but not mobile**

This is expected when using local Convex. See [Mobile OAuth Requirements](#mobile-oauth-requirements-convex) above.

Quick checklist:

1. Is `SITE_URL` set to a public URL? (not `127.0.0.1` or `localhost`)
2. Are OAuth credentials set in Convex Dashboard?
3. Are OAuth provider redirect URLs configured with your `.convex.site` domain?
4. Does your `app.json` have the correct scheme?

**How to debug OAuth flow:**

```bash theme={null}
# Watch Convex logs in real-time
npx convex logs --tail

# Check environment variables
npx convex env list
```

Look for `[Convex Auth]` log messages that show the redirect flow.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Authentication" icon="lock" href="/core-features/authentication">
    Email/password auth and account management
  </Card>

  <Card title="Backend & Database" icon="database" href="/core-features/backend">
    Store user data with your chosen backend
  </Card>
</CardGroup>
