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?

Prerequisites

You need a users table with an auth extension. The default teeny create template includes one. If you started from a blank template, see the Config Reference for how to add the auth extension.

1. Get Google Auth Client ID

  1. Go to the Google Auth Platform Clients Page
  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 (run teeny status after deploying to get this)
  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.

TIP

The CLI prints your URLs when you run teeny dev or teeny 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 (get the URL from teeny status).

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
teeny deploy --remote
teeny secrets --remote --upload
bash
npx teeny deploy --remote
npx teeny secrets --remote --upload

Check your production URL with:

bash
teeny status
bash
npx teeny status