Google Workspace Connector — Setup Guide¶
Step-by-step walkthrough for connecting a Google Workspace domain to Floh. For the full command reference, see google-workspace-connector.md.
1. Create a Service Account¶
- Go to GCP Console > IAM & Admin > Service Accounts
- Select your project (or create one)
- Click Create Service Account
- Name:
floh-workspace-connector - Description:
Floh connector for Google Workspace management - Click Done (skip the optional grant steps)
- Click the new service account → Keys tab → Add Key → Create new key → JSON
- Save the downloaded JSON file securely — you'll need
client_email,private_key, andclient_idfrom it
2. Enable the Required APIs¶
In the same GCP project, go to API Library and enable:
- Admin SDK API (
admin.googleapis.com) - Google Drive API (
drive.googleapis.com)
3. Grant Domain-Wide Delegation¶
- Open the downloaded JSON key file and copy the numeric
client_idvalue - Go to Google Admin Console for your domain
- Navigate to Security → Access and data control → API controls → Manage Domain Wide Delegation
- Click Add new
- Enter:
- Client ID: the numeric
client_idfrom the JSON key file - OAuth scopes (comma-separated, no spaces):
https://www.googleapis.com/auth/admin.directory.user,https://www.googleapis.com/auth/admin.directory.group,https://www.googleapis.com/auth/admin.directory.orgunit.readonly,https://www.googleapis.com/auth/drive
The
admin.directory.orgunit.readonlyscope is required for the workflow designer to populate and validate the orgUnitPath field oncreateUser. Without it, designer lookups against the Org Units API fail with403 insufficientPermissionseven though the rest of the connector works.
- Click Authorize
Note: Domain-wide delegation is configured entirely in the Google Admin Console. The GCP Console no longer has a separate toggle for this.
4. Register the Connector Instance in Floh¶
The google-workspace connector type is seeded automatically on server startup. Create a configured instance by calling:
with the connection config from your JSON key file:
{
"config": {
"serviceAccountEmail": "<client_email from JSON>",
"privateKey": "<private_key from JSON — full PEM string>",
"adminEmail": "<workspace super admin email>",
"customerId": "my_customer"
}
}
| Field | Source | Notes |
|---|---|---|
serviceAccountEmail |
client_email in JSON key file |
e.g. sa@project.iam.gserviceaccount.com |
privateKey |
private_key in JSON key file |
Full PEM string including -----BEGIN/END----- and \n sequences |
adminEmail |
Your Workspace super admin login | The service account impersonates this user |
customerId |
Optional | Defaults to my_customer; find yours in Admin Console → Account → Account settings |
The privateKey is marked as a secret field and is encrypted at rest with AES-256-GCM.
CSRF Note¶
When calling write endpoints via curl in local development, include CSRF headers:
In non-dev environments, use the actual CSRF token and cookie issued by the app.
5. Test the Connection¶
curl -sk -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "x-csrf-token: dev" -b "floh_csrf=dev" \
"https://localhost:7070/api/connectors/<connector-id>/execute" \
-d '{"command": "test"}'
Expected response:
{
"success": true,
"payload": {
"message": "Connection successful",
"tokenObtained": true,
"adminEmail": "admin@example.com",
"customerId": "my_customer"
}
}
Then verify each domain:
Troubleshooting¶
| Error | Cause | Fix |
|---|---|---|
"pkcs8" must be PKCS#8 formatted string |
privateKey is missing or malformed |
Use the full private_key value from the JSON file (not the private_key_id) |
Not a valid email or user ID |
serviceAccountEmail typo, or adminEmail doesn't exist in the domain, or delegation not configured |
Verify all three: service account email matches client_email, admin email is a real super admin, and the Client ID + scopes are saved in Admin Console |
Invalid or missing CSRF token |
Write request missing CSRF headers | Add -H "x-csrf-token: dev" -b "floh_csrf=dev" to curl |
Forbidden / 403 from Google |
Scopes not authorized in domain-wide delegation | Re-check the delegation entry in Admin Console — ensure all four scopes are listed (user, group, orgunit.readonly, drive) |
403 insufficientPermissions on orgUnitPath lookup in the workflow designer |
DWD entry pre-dates the admin.directory.orgunit.readonly scope |
Edit the existing DWD entry and add https://www.googleapis.com/auth/admin.directory.orgunit.readonly, then save |