Google Workspace Delegated Access Setup

Tempr's Calendar import and webhook paths use a Google Workspace service account with domain-wide delegation.

This page documents how to create the Google Cloud credential and authorize its delegated access in the Google Admin console.

Use this before running the Google Calendar import service or Google Calendar webhook setup.

What Tempr Needs

Tempr currently authenticates to Google Calendar through:

src/Modules/Calendar/Services/GoogleWorkspaceClientFactory.php

That factory loads service account JSON credentials and impersonates a Workspace user with:

$client->setSubject($subject);

Because of that, Tempr needs:

  • a Google Cloud project
  • enabled Google Workspace APIs
  • a service account with domain-wide delegation
  • a service account JSON key available to the app
  • the service account's numeric OAuth Client ID authorized in Google Admin
  • the smallest required OAuth scopes delegated to that client ID

Do not use a user-consent OAuth web client for this Calendar import path. In Google Admin, the delegated access screen calls the service account identifier a Client ID. That is the numeric OAuth Client ID from the service account's advanced settings.

Required APIs

In the Google Cloud project, enable:

  • Google Calendar API
  • Admin SDK API

The Admin SDK API is only required for Workspace-wide user discovery, such as:

php artisan calendar:import-google --workspace

Required Delegated Scopes

Authorize these scopes for Tempr Calendar import and webhook sync:

https://www.googleapis.com/auth/calendar.readonly
https://www.googleapis.com/auth/calendar.calendarlist.readonly
https://www.googleapis.com/auth/admin.directory.user.readonly

Scope usage:

ScopeUsed for
calendar.readonlyReading calendar event data and creating Calendar API event watch channels.
calendar.calendarlist.readonlyDiscovering calendars visible to an impersonated Workspace user.
admin.directory.user.readonlyListing active Workspace users for calendar:import-google --workspace.

If an environment will never run Workspace-wide discovery, the Directory scope can be omitted. Production credentials normally include all three so one credential supports imports, webhooks, and workspace discovery.

Step 1: Create Or Select A Google Cloud Project

Use a dedicated Google Cloud project for Tempr Workspace automation.

Recommended project ownership:

  • owned by the organization's Google Cloud organization
  • limited editor access
  • billing configured if required by the organization
  • no unrelated workloads

Step 2: Enable APIs

In Google Cloud Console:

  1. Open the project.
  2. Go to APIs & Services > Library.
  3. Enable Google Calendar API.
  4. Enable Admin SDK API.

Step 3: Create The Service Account

In Google Cloud Console:

  1. Go to IAM & Admin > Service Accounts.
  2. Click Create service account.
  3. Use a clear name, such as tempr-calendar-sync.
  4. Add a description, such as Tempr Calendar import and webhook sync.
  5. Finish service account creation.

The service account does not need broad project roles for Calendar API access through domain-wide delegation. Keep project-level permissions minimal.

Step 4: Enable Domain-Wide Delegation

Open the service account and enable domain-wide delegation:

  1. Go to IAM & Admin > Service Accounts.
  2. Open the service account.
  3. Find Advanced settings.
  4. Enable or confirm Domain-wide delegation.
  5. Copy the service account's numeric Client ID.

This numeric Client ID is what the Google Admin console authorizes.

The service account email and the service account numeric Client ID are different values. The Admin console wants the numeric Client ID.

Step 5: Create The JSON Key

Create a JSON key for the service account:

  1. Open the service account.
  2. Go to Keys.
  3. Click Add key.
  4. Choose Create new key.
  5. Select JSON.
  6. Download the key.

Store the JSON file in the app's configured secrets/storage location. Do not commit it to git.

Tempr reads the path from:

.env
CALENDAR_GOOGLE_CREDENTIALS_JSON=/absolute/path/to/google-service-token.json

Step 6: Authorize The Client In Google Admin

This step must be completed by a Google Workspace super administrator.

In Google Admin Console:

  1. Go to Security > Access and data control > API controls.
  2. Open Manage Domain Wide Delegation.
  3. Click Add new.
  4. Paste the service account's numeric Client ID into Client ID.
  5. Paste the required OAuth scopes into OAuth scopes.
  6. Click Authorize.

Use a comma-delimited scope list:

https://www.googleapis.com/auth/calendar.readonly,https://www.googleapis.com/auth/calendar.calendarlist.readonly,https://www.googleapis.com/auth/admin.directory.user.readonly

Step 7: Configure Tempr

Set or confirm:

.env
CALENDAR_GOOGLE_CREDENTIALS_JSON=/absolute/path/to/google-service-token.json
CALENDAR_GOOGLE_DEFAULT_USER=admin-or-calendar-user@example.com
CALENDAR_GOOGLE_WORKSPACE_CUSTOMER=my_customer
CALENDAR_GOOGLE_PAGE_SIZE=100
CALENDAR_IMPORT_QUEUE=default

For webhooks, also set:

.env
CALENDAR_GOOGLE_WEBHOOK_URL=https://your-public-host.example.com/integrations/google/calendar/webhooks/callback
CALENDAR_GOOGLE_WEBHOOK_TTL_SECONDS=604800
CALENDAR_GOOGLE_WEBHOOK_RENEWAL_THRESHOLD=86400

Clear cached config:

php artisan optimize:clear

Step 8: Smoke Test Access

Test one known user:

php artisan calendar:import-google --user=scheduler@example.com --dry-run

If Workspace discovery is enabled, test a small user limit:

php artisan calendar:import-google --workspace --max-users=1 --dry-run

Then run a real import:

php artisan calendar:import-google --user=scheduler@example.com --sync

After sources exist, create webhook channels:

php artisan calendar:google-webhooks:sync

Troubleshooting

Invalid Grant Or Unauthorized Client

Common causes:

  • Domain-wide delegation is not enabled on the service account.
  • The Admin console authorized the service account email instead of the numeric Client ID.
  • The subject user does not exist in the Workspace domain.
  • The service account JSON belongs to a different service account than the Admin console entry.

Insufficient Permission

Check the delegated scopes in Google Admin.

The Calendar import path needs:

https://www.googleapis.com/auth/calendar.readonly
https://www.googleapis.com/auth/calendar.calendarlist.readonly

Workspace discovery needs:

https://www.googleapis.com/auth/admin.directory.user.readonly

Workspace Import Finds No Users

Check:

  • Admin SDK API is enabled.
  • CALENDAR_GOOGLE_WORKSPACE_CUSTOMER is correct.
  • admin.directory.user.readonly is authorized.
  • CALENDAR_GOOGLE_DEFAULT_USER can impersonate a Workspace user in the domain.

Calendar Import Finds No Calendars

Check:

  • Google Calendar API is enabled.
  • calendar.calendarlist.readonly is authorized.
  • The impersonated user has access to the calendar.
  • The target calendar is not hidden, or run with --include-hidden.

Security Notes

  • Grant only the scopes Tempr needs.
  • Keep the service account in a dedicated Google Cloud project.
  • Restrict who can edit the project and service account.
  • Rotate JSON keys if they are exposed.
  • Remove old Admin console domain-wide delegation entries when credentials are retired.
  • Review delegated clients regularly in Google Admin.

Official References