Google auth
The one Google OAuth client and grant that Calendar, Gmail, and Drive share: creating it, authorizing it, where the tokens live, and what to do when the grant dies.
What it is
This guide walks through setting up Google OAuth2 credentials for Bee Box. These credentials are shared across all Google connectors (Calendar, Gmail API, Drive).
Create a Google Cloud project
- Go to console.cloud.google.com
- Click the project dropdown at the top → New Project
- Name it something like "Bee Box"
- Click Create
Enable APIs
In your new project, go to APIs & Services → Library and enable:
- Google Calendar API
- Gmail API
- Google Drive API
- Google Sheets API (required for reading/writing spreadsheet cell values)
Search for each one and click Enable.
Configure the OAuth consent screen
Go to APIs & Services → OAuth consent screen:
- User type: External (even for personal use)
- App name: "Bee Box" (only you see this)
- User support email: your email
- Developer contact: your email
- Click through the rest — no need to add scopes here (they're requested at auth time)
- Under Test users, add your Google email address
- Leave the app in Testing mode — no need to publish for personal use
Note: In Testing mode, tokens expire every 7 days and you'll need to re-auth. If this becomes annoying, you can publish the app (it won't be listed anywhere since there's no homepage/verification).
Create OAuth credentials
Go to APIs & Services → Credentials:
- Click Create Credentials → OAuth 2.0 Client ID
- Application type: Web application (not Desktop)
- Name: "Bee Box" (or anything)
- Under Authorized redirect URIs, add the URIs for your setup:
- Web (recommended):
https://<your-server>/auth/google-services/callback - CLI:
http://localhost:8976/oauth/callback
- Web (recommended):
- Click Create
- Copy the Client ID and Client Secret. They serve two different surfaces, configured two different ways:
- App login (signing in to beebox itself, before any box exists) reads them from the
GOOGLE_OAUTH_CLIENT_IDandGOOGLE_OAUTH_CLIENT_SECRETenv vars on the server — set those there. - A box's Google connectors (Calendar, Gmail, Drive) resolve the same pair from the machine secret store instead:
bbx secrets set google-oauth-client-id,bbx secrets set google-oauth-client-secret, thenbbx secrets grant <box> google-oauth-client-id(and the-secretname) for each box that needs them. Env vars are not read for this path.
- App login (signing in to beebox itself, before any box exists) reads them from the
Where tokens live
BBX_GOOGLE_TOKENS_FILE names a token file shared by every box that sees it (e.g., /home/beebox/.google-tokens.json). On a unit host, where each box is its own user and the variable is not passed to boxes, each box keeps its own token at ~/.config/beebox/google-tokens.json in the box user's home. Otherwise tokens fall back to per-box _config/connectors/google.secret.json, inside the box tree; bbx health warns about that file.
Authorize Bee Box
Web admin (recommended)
- Go to any box's Admin page
- In the Google Services section, click Connect Google Account
- You'll be redirected to Google for authorization
- After approving, you'll be redirected back. With
BBX_GOOGLE_TOKENS_FILE, every box that shares that file now has the token; on a unit host (the server), only the box you connected from has it, so connect each box that needs Google
Per-box service policy
After connecting, enable specific services per box in each box's Admin page (Calendar, Gmail, Drive toggles). Or edit _config/box.json directly:
{
"googleServices": {
"calendar": true,
"gmail": false,
"drive": false
}
}
If googleServices is missing, no Google services are enabled for that box (safe default).
Verify
Each connector's page has its own verify step; the quickest end-to-end check is the calendar pull.
Scopes authorized
| Scope | Description |
|---|---|
calendar.events | Read and write calendar events |
gmail.readonly | Read all email |
gmail.compose | Create drafts and send email |
drive.readonly | Read all Drive files |
drive.file | Read/write files created by the app |
spreadsheets | Read and write Google Sheets |
Troubleshooting
redirect_uri_mismatch
The redirect URI in your OAuth client must exactly match the one you're using. For CLI: http://localhost:8976/oauth/callback. For web: https://<your-server>/auth/google-services/callback. Check for trailing slashes or https vs http.
Token expired / invalid_grant
Google grants die on their own. If your OAuth consent screen is in Testing mode, refresh tokens expire every 7 days; an unverified Production app can also have its grant revoked. This is a property of BYO Google credentials, not a defect in the box.
The box detects it and says so rather than failing quietly. When a token refresh comes back invalid_grant:
bbx health(and the dashboard's health warnings) reportgoogle-auth: Google authorization expired or was revoked … Reconnect at /<box>/admin?reconnect=google.- The boxholder gets one notification per breakage over whatever channels are configured (the iPhone app, Web Push), with the same link. There's no re-nag — the health condition persists until it's fixed.
- Gmail, Calendar and Drive sync pause; the rest of the box keeps working.
Reconnect from the admin page's Google Services section (Re-authorize). The new grant clears the condition automatically.
The state is stored with the credential, so on a server sharing one BBX_GOOGLE_TOKENS_FILE across boxes, reconnecting once fixes every box.
Design notes: implemented-plans/google-auth-reauth-health.md.