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

> [tab] 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] 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.

***

## Quick Start

> [tab] 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] 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>
>   )
> }
> ```

***

## Google Sign-In Setup

> [tab] 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] 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
> ```

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

> [tab] 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] 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))

***

## Mobile OAuth Requirements (Convex)

> [!WARNING]
>
> This section applies only to **Convex** backends. Supabase OAuth works with local development.

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

### Development Options

> [accordion] 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
> ```
>
> > [!NOTE]
> >
> > 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`.

> [accordion] 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.

> [accordion] 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.

### 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"
  }
}
```

> [!NOTE]
>
> **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.

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

> [!NOTE]
>
> Web OAuth works automatically with Shipnative! Just ensure your redirect URLs are configured correctly.

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

> [tab] 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] Convex
>
> Configure redirect URLs in your Convex auth configuration and ensure your deployment URL is set up correctly in the Convex Dashboard.

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

> [card] [Authentication](https://docs.shipnative.app/core-features/authentication.md)
>
> Email/password auth and account management

> [card] [Backend & Database](https://docs.shipnative.app/core-features/backend.md)
>
> Store user data with your chosen backend


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.