---
title: "Google One Tap / SPA"
description: "Add Google One Tap or SPA sign-in to teenybase: Google gives the browser a credential and your frontend sends it to teenybase to sign the user in."
url: https://teenybase.com/docs/guides/google-oauth-onetap
last_updated: 2026-10-26
---

> Documentation index: https://teenybase.com/llms.txt lists every teenybase docs page with a link to its Markdown version. All docs in one file: https://teenybase.com/llms-full.txt

# Google One Tap / SPA

Add Google One Tap login to a single-page app. Google gives you the credential in the browser, your frontend sends it to teenybase.

> **Using a coding agent?** Paste this prompt:
>
> Add Google One Tap login to my teenybase SPA..

## Prerequisites

You need a `users` table with an `auth` extension. The default `npx teenybase create` template includes one. If you started from a blank template, see the [Config Reference](https://teenybase.com/docs/reference/config-reference#auth-extension-tableauthextensiondata) for how to add the auth extension.

## 1. Get Google Auth Client ID

1. Go to the [Google Auth Platform Clients Page](https://console.developers.google.com/auth/clients)
2. Select your project. Create one if you don't have one.
3. Click **Create client**
4. Application type: **Web application**
5. Add authorized JavaScript origins:
   - `http://localhost:8787` (local dev)
   - Your production URL (the URL `npx teenybase deploy --remote` prints, also saved as `apiRoute` in `infra.jsonc`)
6. Copy the **Client ID**. You do not need the Client Secret for this flow.

Redirect URIs are not needed for One Tap. Only JavaScript origins.

For the full Google setup walkthrough, see the [official guide](https://support.google.com/cloud/answer/15549257?hl=en).

> **Tip**
>
> The CLI prints your URLs when you run `npx teenybase dev` or `npx teenybase deploy --remote`. You don't need to construct them manually.

## 2. Add secrets

In `.dev.vars`, add:

```env
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
```

## 3. Add config

In `teenybase.ts`:

```ts
export default {
  // ...existing config...

  authProviders: [
    {
      name: 'google',
      clientId: '$GOOGLE_CLIENT_ID',
    },
  ],

} satisfies DatabaseSettings
```

## 4. One Tap (browser popup)

Add the Google script to your HTML. Replace `YOUR_CLIENT_ID` with your Google Client ID:

```html
<script src="https://accounts.google.com/gsi/client" async></script>
<div id="g_id_onload"
  data-client_id="YOUR_CLIENT_ID"
  data-login_uri="http://localhost:8787/api/v1/table/users/auth/google-login"
  data-auto_prompt="true">
</div>
```

In production, replace `data-login_uri` with `YOUR_PRODUCTION_URL/api/v1/table/users/auth/google-login` (the production URL is `apiRoute` in `infra.jsonc`).

Google posts the credential to your teenybase endpoint. Teenybase verifies the JWT, creates or finds the user, and returns:

```json
{ "token": "...", "refresh_token": "...", "record": { ... } }
```

## 5. SPA (Bearer token)

If you're using the Google JS SDK directly (e.g. in React), get the credential client-side and send it as a Bearer token:

```js
const API = 'http://localhost:8787/api/v1'

const res = await fetch(`${API}/table/users/auth/login-token`, {
  method: 'POST',
  headers: { 'Authorization': `Bearer ${googleCredential}` },
})
const { token, refresh_token, record } = await res.json()
```

Store the token and use it for subsequent requests:

```js
const posts = await fetch(`${API}/table/posts/select`, {
  headers: { 'Authorization': `Bearer ${token}` },
})
```

### Example: full login flow in React

```js
// After Google gives you the credential:
async function handleGoogleLogin(googleCredential) {
  const res = await fetch(`${API}/table/users/auth/login-token`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${googleCredential}` },
  })
  const { token, refresh_token, record } = await res.json()

  // Store these in your app state
  localStorage.setItem('token', token)
  localStorage.setItem('refresh_token', refresh_token)

  // User is now logged in
  console.log('Logged in as', record.email)
}
```

## 6. Deploy to production

Add the same secret to `.prod.vars`:

```env
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
```

Update `appUrl` in `teenybase.ts` to your production frontend URL if needed.

```bash
npx teenybase deploy --remote --yes
npx teenybase secrets --remote --upload
```

Your production URL is saved as `apiRoute` in `infra.jsonc`.
