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

# Google OAuth

> Add "Continue with Google" sign-in by creating an OAuth 2.0 Client in Google Cloud and dropping two env vars.

The "Continue with Google" button on `/login` and `/register` light up automatically
once `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` are set. There is no provider
code to write — Better Auth handles the OAuth dance, and the auto-link logic in
`src/lib/auth.ts` merges Google sign-ins with existing email accounts.

## Prerequisites

* A Google account.
* Your production domain decided (you can develop locally first).
* 10 minutes — most of it is filling in the OAuth consent screen.

## Step-by-step setup

1. **Open Google Cloud Console** at [console.cloud.google.com](https://console.cloud.google.com)
   and create (or pick) a project. Each product gets its own project.

2. **Configure the OAuth consent screen.** Under APIs & Services → OAuth consent
   screen, pick "External" user type. Fill in app name, support email, and a logo.
   The scopes you need are the defaults: `userinfo.email`, `userinfo.profile`,
   `openid`. Add your production domain as an authorized domain.

3. **Create OAuth 2.0 credentials.** APIs & Services → Credentials →
   Create Credentials → OAuth client ID. Application type: **Web application**.

4. **Set authorized redirect URIs.** Better Auth's callback path is
   `/api/auth/callback/google`. Add both your local and production URIs:

   ```
   http://localhost:3000/api/auth/callback/google
   https://your-domain.com/api/auth/callback/google
   ```

   If you preview on Vercel, add the preview URL too.

5. **Copy the client ID + secret into `.env.local`:**

   ```bash theme={null}
   GOOGLE_CLIENT_ID=1234567890-abc...apps.googleusercontent.com
   GOOGLE_CLIENT_SECRET=GOCSPX-...
   # Mirror the ID for client-side One-Tap (see /docs/auth/one-tap)
   NEXT_PUBLIC_GOOGLE_CLIENT_ID=1234567890-abc...apps.googleusercontent.com
   ```

6. **Enable the button.** In `src/config/site.ts`:

   ```ts theme={null}
   features: { enableGoogleLogin: true, /* ... */ }
   ```

7. **Restart dev server.** Env vars are read at startup — `pnpm dev` after each
   `.env.local` edit.

## What happens behind the scenes

When the user clicks "Continue with Google", `authClient.signIn.social({ provider:
'google', callbackURL: '/dashboard' })` runs. Better Auth redirects to Google,
Google bounces back to `/api/auth/callback/google`, and the callback handler:

1. Exchanges the auth code for an access + ID token.
2. Looks up the email in `account` (`providerId = 'google'`). If found, sign in.
3. If not found but the email matches an existing `user`, link a new `account` row
   (account-linking is on for trusted providers — see `src/lib/auth.ts`).
4. If no match, create a new `user` + `account` and fire the post-create hook
   (which grants register-gift credits and promotes to admin if applicable).

You can watch this happen in the dev console — Better Auth logs each step with the
`[better-auth]` prefix.

## Verify it works

1. Visit `/login` — the "Continue with Google" button should be visible.
2. Click it. You bounce to `accounts.google.com`, pick an account, and land back
   on `/dashboard`.
3. Check the `account` table — there should be a row with `providerId = 'google'`
   linked to your `user` row.
4. Sign out and sign back in with Google. Same `user` id, no duplicate row.

## Common pitfalls

* **`redirect_uri_mismatch` error.** You typed the redirect URI wrong in the Google
  console. Trailing slashes matter; `http` vs `https` matters; localhost port matters.
  Copy-paste from the list above.
* **Localhost works, production doesn't.** You only added the localhost URI. Add the
  production URI to the same OAuth client (you can have many redirect URIs per client).
* **OAuth consent screen stuck "Testing".** While in Testing, only the test users
  you list can sign in. Click **Publish App** for general availability. Production
  apps usually do not need verification unless you ask for sensitive scopes.
* **`NEXT_PUBLIC_GOOGLE_CLIENT_ID` missing.** Causes One-Tap to silently no-op.
  See [One-Tap docs](/auth/one-tap).
* **Different domains in dev vs preview vs prod.** Each gets its own redirect URI
  entry. There's no wildcard support.
* **Refresh tokens not requested.** Better Auth uses the standard `online` access
  type — fine for sign-in. If you later need to call Google APIs on the user's
  behalf, you'll need offline access and a refresh token; pass `accessType: 'offline'`
  in your provider config.

## Official docs

* Using OAuth 2.0 for Web Server Apps — [developers.google.com/identity/protocols/oauth2/web-server](https://developers.google.com/identity/protocols/oauth2/web-server)
* OAuth consent screen setup — [support.google.com/cloud/answer/10311615](https://support.google.com/cloud/answer/10311615)
* Better Auth Google provider — [better-auth.com/docs/authentication/google](https://www.better-auth.com/docs/authentication/google)
