Skip to content

Google OAuth setup

1. Create a Google Cloud project and OAuth client

Section titled “1. Create a Google Cloud project and OAuth client”
  1. Open Google Cloud Console and create (or select) a project.
  2. Navigate to APIs & Services → Credentials → Create Credentials → OAuth 2.0 Client ID.
  3. Set the application type to Web application.

Add both of the following as Authorized redirect URIs in your OAuth client. Replace https://book.example.com with your actual APP_BASE_URL:

${APP_BASE_URL}/api/google/callback
${APP_BASE_URL}/api/google/login/callback

Both URIs must be registered — one is used for the per-user Calendar connection flow, the other for Google sign-in.

Copy the Client ID and Client Secret from the Credentials page, then set:

GOOGLE_OAUTH_CLIENT_ID=your-client-id
GOOGLE_OAUTH_CLIENT_SECRET=your-client-secret
# Strong random string shared by ALL replicas
GOOGLE_OAUTH_STATE_SECRET=<openssl rand -hex 32>

GOOGLE_OAUTH_STATE_SECRET must be the same value on every replica. Generate it with:

Terminal window
openssl rand -hex 32

TOKEN_ENCRYPTION_KEY encrypts stored Google OAuth tokens with AES-256-GCM. See the Configuration reference for details.

Each user connects their own Google account from the owner console (/me). Once connected, every new booking automatically:

  • Creates a Google Calendar event on the user’s calendar.
  • Generates a Google Meet link included in the booking confirmation.

Until your OAuth app is verified, Google shows users an “Google hasn’t verified this app” warning and caps the app at 100 new users (a per-project lifetime cap that cannot be reset). To remove the warning and lift the cap, complete verification in the Google Cloud Console:

  1. Set OPERATOR_NAME and PRIVACY_CONTACT_EMAIL (see configuration). calit then serves a complete privacy policy at ${APP_BASE_URL}/privacy and terms at ${APP_BASE_URL}/terms, including the required Google Limited Use disclosure.
  2. On the OAuth consent screen, set the privacy-policy link to ${APP_BASE_URL}/privacy (and, optionally, terms to ${APP_BASE_URL}/terms).
  3. Verify domain ownership — either set GOOGLE_SITE_VERIFICATION to the token from Google Search Console (calit renders the <meta> tag on every page), or add the DNS TXT record Google offers.
  4. Submit for verification.

A Google connection can break without warning — access is revoked, the account password is changed, or the refresh token simply expires. calit detects this and fails closed: while an owner’s Google account is disconnected, their public booking page shows “Scheduling temporarily unavailable” instead of offering every slot as free. This prevents bookings landing on top of calendar events calit can no longer see.

Each connected account is probed on a schedule (every GOOGLE_PROBE_INTERVAL, default 1h) for a still-valid connection; the probe also keeps the refresh token warm. When a disconnect is found, the owner is emailed once per outage with a link to reconnect on the /me/google settings page.