EasyStarter logoEasyStarter

Authentication Service

Configure Better Auth, Google OAuth, and Apple native sign-in

Authentication

EasyStarter's mobile app uses Better Auth for authentication, with the following built-in providers:

  • Email + password login
  • Google OAuth
  • Apple native sign-in (iOS only)

Server configuration lives in apps/server/src/lib/auth.ts. Apple Sign-In uses the native ID token flow: the app triggers the system-level Apple sign-in sheet, retrieves the identityToken, and passes it directly to Better Auth for verification — no web redirect needed.

Required Environment Variables

Server

BETTER_AUTH_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
APPLE_APP_BUNDLE_IDENTIFIER=

Get BETTER_AUTH_SECRET

BETTER_AUTH_SECRET is used by Better Auth to sign and encrypt session data. It must be a sufficiently long random string.

openssl rand -base64 32

Copy the output and add it to both local and production environments:

apps/server/.dev.vars
BETTER_AUTH_SECRET=your-long-random-secret
apps/server/.env.production
BETTER_AUTH_SECRET=your-long-random-secret

Create Google OAuth Client

Google Cloud Console: Google Cloud Console

  1. Log in and select or create a project
  2. Go to APIs & Services > Credentials
  3. Click Create Credentials → select OAuth client ID
  4. Complete the OAuth consent screen if prompted
  5. Select Web application as the application type
  6. Configure the redirect URI

Key fields:

  • Authorized JavaScript origins: your frontend URL, e.g. https://yourdomain.com
  • Authorized redirect URIs: {SERVER_URL}/api/auth/callback/google

Mobile Google OAuth requires an HTTPS callback URL. Use ngrok to expose your local server over HTTPS.

Why ngrok is required for mobile development

Mobile Google Sign-In uses a deep link callback flow, not a simple browser redirect:

  1. The app opens Google's login page via expo-web-browser
  2. After the user logs in, Google redirects to the server callback URL (SERVER_URL/api/auth/callback/google)
  3. The server processes the callback, then redirects the user back to the app via a deep link (e.g. myapp://callback)
  4. The OS intercepts the deep link, relaunches the app, and the login completes

This flow has two hard requirements:

  • Google OAuth enforces HTTPShttp://localhost is not accepted
  • Physical devices and simulators cannot access your dev machine's localhost directly — the server must have a publicly reachable address

ngrok solves both: it exposes your local localhost:3001 as a public HTTPS URL, so Google can complete the redirect and the server can send the user back to the app via deep link.

Install ngrok

Download and install from the ngrok website, or use Homebrew:

brew install ngrok

After installing, sign up for a free account and authenticate:

ngrok config add-authtoken YOUR_AUTH_TOKEN

Find your Auth Token at ngrok Dashboard → Your Authtoken.

Start the tunnel

After starting the local server (pnpm dev:server), open a new terminal and run:

ngrok http 3001

ngrok will output an HTTPS URL like:

Forwarding  https://xxxx-xxxx.ngrok-free.app -> http://localhost:3001

Use this URL as the Google OAuth redirect URI:

https://xxxx-xxxx.ngrok-free.app/api/auth/callback/google

Also update SERVER_URL in .dev.vars to this ngrok URL so Better Auth's baseURL and the OAuth callback stay in sync.

Note: The free ngrok plan generates a new URL on every restart. You'll need to update both the Google Cloud Console redirect URI and your local .dev.vars each time.

After creating, you'll receive:

  • Client IDGOOGLE_CLIENT_ID
  • Client SecretGOOGLE_CLIENT_SECRET

Configure Apple Native Sign-In

The mobile Apple Sign-In uses the native iOS flow: the app calls expo-apple-authentication to trigger the system sign-in sheet, retrieves the Identity Token, and the server validates it using the Bundle ID (APPLE_APP_BUNDLE_IDENTIFIER) as the audience.

Reference: Better Auth Apple docs

Enable Sign In with Apple on your App ID

The App ID was already created in the Configure app.json chapter. Now enable Apple Sign-In on it:

  1. Log in to Apple Developer Portal → Identifiers
  2. Find and click your App ID
  3. Under Capabilities, check Sign In with Apple
  4. Click Continue → Save

Create and configure a Service ID

  1. In Identifiers, click +, select Service IDs → Continue
  2. Enter a Description and Identifier (e.g. com.yourcompany.yourapp.si) — this becomes your APPLE_CLIENT_ID
  3. Click Register
  4. Click the Service ID you just created → check Sign In with Apple → click Configure
  5. Under Primary App ID, select your App ID
  6. Configure Domains and Subdomains and Return URLs:
EnvironmentDomains and SubdomainsReturn URLs
Developmentxxxx-xxxx.ngrok-free.apphttps://xxxx-xxxx.ngrok-free.app/api/auth/callback/apple
Productionserver.yourdomain.comhttps://server.yourdomain.com/api/auth/callback/apple

In development, use your ngrok URL. Remember to update both the Domain and Return URL here every time ngrok restarts. In production, use your actual server domain.

  1. Click Next → Done → Continue → Save

Set Environment Variables

For local development, add everything to apps/server/.dev.vars:

apps/server/.dev.vars
BETTER_AUTH_SECRET=your-long-random-secret
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
APPLE_APP_BUNDLE_IDENTIFIER=com.yourcompany.yourapp

For production, put sensitive values in apps/server/.env.production:

apps/server/.env.production
BETTER_AUTH_SECRET=your-long-random-secret
GOOGLE_CLIENT_SECRET=your-google-client-secret

Add non-sensitive IDs to vars in apps/server/wrangler.jsonc:

apps/server/wrangler.jsonc
"vars": {
  "GOOGLE_CLIENT_ID": "your-google-client-id",
  "APPLE_APP_BUNDLE_IDENTIFIER": "com.yourcompany.yourapp"
}

How Better Auth Works in the Mobile App

The mobile authClient is configured in apps/native/lib/auth/auth.client.ts, using the @better-auth/expo adapter to handle deep link callbacks and cookie storage.

Currently supported:

  • Email/password signup and login
  • Google OAuth (via deep link callback)
  • Apple native sign-in (via ID token, iOS only)
  • Cookie-based cross-platform session management

Apple Sign-In is only available on physical devices and TestFlight. It does not work in the iOS Simulator.