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.
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
- Go to the Google Auth Platform Clients Page
- Select your project. Create one if you don't have one.
- Click Create client
- Application type: Web application
- Add authorized JavaScript origins:
http://localhost:8787(local dev)- Your production URL (run
teeny statusafter deploying to get this)
- 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:
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com3. Add config
In teenybase.ts:
export default {
// ...existing config...
authProviders: [
{
name: 'google',
clientId: '$GOOGLE_CLIENT_ID',
},
],
} satisfies DatabaseSettings4. One Tap (browser popup)
Add the Google script to your HTML. Replace YOUR_CLIENT_ID with your Google Client ID:
<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:
{ "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:
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:
const posts = await fetch(`${API}/table/posts/select`, {
headers: { 'Authorization': `Bearer ${token}` },
})Example: full login flow in React
// 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:
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.comUpdate appUrl in teenybase.ts to your production frontend URL if needed.
teeny deploy --remote
teeny secrets --remote --uploadnpx teeny deploy --remote
npx teeny secrets --remote --uploadCheck your production URL with:
teeny statusnpx teeny status