11 KiB
Google Workspace Directory Integration
This document provides technical documentation for the Google Workspace (formerly G Suite) directory integration in Bitwarden Directory Connector.
Overview
The Google Workspace integration synchronizes users and groups from Google Workspace to Bitwarden organizations using the Google Admin SDK Directory API. The service uses a service account with domain-wide delegation to authenticate and access directory data.
Architecture
Service Location
- Implementation:
src/services/directory-services/gsuite-directory.service.ts - Configuration Model:
src/models/gsuiteConfiguration.ts - Integration Tests:
src/services/directory-services/gsuite-directory.service.integration.spec.ts
Authentication Flow
The Google Workspace integration uses OAuth 2.0 with Service Accounts and domain-wide delegation:
- A service account is created in Google Cloud Console
- The service account is granted domain-wide delegation authority
- The service account is authorized for specific OAuth scopes in Google Workspace Admin Console
- The Directory Connector uses the service account's private key to generate JWT tokens
- JWT tokens are exchanged for access tokens to call the Admin SDK APIs
Required OAuth Scopes
The service account must be granted the following OAuth 2.0 scopes:
https://www.googleapis.com/auth/admin.directory.user.readonly
https://www.googleapis.com/auth/admin.directory.group.readonly
https://www.googleapis.com/auth/admin.directory.group.member.readonly
Configuration
Required Fields
| Field | Description |
|---|---|
clientEmail |
Service account email address (e.g., service-account@project.iam.gserviceaccount.com) |
privateKey |
Service account private key in PEM format |
adminUser |
Admin user email to impersonate for domain-wide delegation |
domain |
Primary domain of the Google Workspace organization |
Optional Fields
| Field | Description |
|---|---|
customer |
Customer ID for multi-domain organizations (rarely needed) |
Example Configuration
{
clientEmail: "directory-connector@my-project.iam.gserviceaccount.com",
privateKey: "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
adminUser: "admin@example.com",
domain: "example.com",
customer: "" // Usually not required
}
Setup Instructions
1. Create a Service Account
- Go to Google Cloud Console
- Create or select a project
- Navigate to IAM & Admin > Service Accounts
- Click Create Service Account
- Enter a name and description
- Click Create and Continue
- Skip granting roles (not needed for this use case)
- Click Done
2. Generate Service Account Key
- Click on the newly created service account
- Navigate to the Keys tab
- Click Add Key > Create new key
- Select JSON format
- Click Create and download the key file
- Extract
client_emailandprivate_keyfrom the JSON file
3. Enable Domain-Wide Delegation
- In the service account details, click Show Advanced Settings
- Under Domain-wide delegation, click Enable Google Workspace Domain-wide Delegation
- Note the Client ID (numeric ID)
4. Authorize the Service Account in Google Workspace
- Go to Google Workspace Admin Console
- Navigate to Security > API Controls > Domain-wide Delegation
- Click Add new
- Enter the Client ID from step 3
- Enter the following OAuth scopes (comma-separated):
https://www.googleapis.com/auth/admin.directory.user.readonly, https://www.googleapis.com/auth/admin.directory.group.readonly, https://www.googleapis.com/auth/admin.directory.group.member.readonly - Click Authorize
5. Configure Directory Connector
Use the extracted values to configure the Directory Connector:
- Client Email: From
client_emailin the JSON key file - Private Key: From
private_keyin the JSON key file (keep the\nline breaks) - Admin User: Email of a super admin user in your Google Workspace domain
- Domain: Your primary Google Workspace domain
Sync Behavior
User Synchronization
The service synchronizes the following user attributes:
| Google Workspace Field | Bitwarden Field | Notes |
|---|---|---|
id |
referenceId, externalId |
User's unique Google ID |
primaryEmail |
email |
Normalized to lowercase |
suspended OR archived |
disabled |
User is disabled if suspended or archived |
| Deleted status | deleted |
Set to true for deleted users |
Special Behavior:
- The service queries both active users and deleted users separately
- Suspended and archived users are included but marked as disabled
- Deleted users are included with the
deletedflag set to true
Group Synchronization
The service synchronizes the following group attributes:
| Google Workspace Field | Bitwarden Field | Notes |
|---|---|---|
id |
referenceId, externalId |
Group's unique Google ID |
name |
name |
Group display name |
| Members (type=USER) | userMemberExternalIds |
Individual user members |
| Members (type=GROUP) | groupMemberReferenceIds |
Nested group members |
| Members (type=CUSTOMER) | userMemberExternalIds |
All domain users |
Member Types:
- USER: Individual user accounts (only ACTIVE status users are synced)
- GROUP: Nested groups (allows group hierarchy)
- CUSTOMER: Special member type that includes all users in the domain
Filtering
The service supports Google Workspace Directory API query syntax for filtering:
User Filter Examples
|orgUnitPath='/Engineering' # Users in Engineering OU
|email:john* # Users with email starting with "john"
|orgUnitPath='/Sales' email:*@example.com # Combined filter
Group Filter Examples
|name:Engineering* # Groups starting with "Engineering"
|email:team-* # Groups with email starting with "team-"
Filter Syntax:
- Prefix with
|for custom filters - Use
:for pattern matching (supports*wildcard) - Combine multiple conditions with spaces (AND logic)
Pagination
The service automatically handles pagination for all API calls:
- Users API (active and deleted)
- Groups API
- Group Members API
Each API call processes all pages using the nextPageToken mechanism until no more results are available.
Error Handling
Common Errors
| Error | Cause | Resolution |
|---|---|---|
| "dirConfigIncomplete" | Missing required configuration fields | Verify all required fields are provided |
| "authenticationFailed" | Invalid credentials or unauthorized | Check service account key and domain-wide delegation setup |
| API returns 401/403 | Missing OAuth scopes | Verify scopes are authorized in Admin Console |
| API returns 404 | Invalid domain or customer ID | Check domain configuration |
Security Considerations
The service implements the following security measures:
- Credential sanitization: Error messages do not expose private keys or sensitive credentials
- Secure authentication: Uses OAuth 2.0 with JWT tokens, not API keys
- Read-only access: Only requires read-only scopes for directory data
- No credential logging: Service account credentials are not logged
Testing
Integration Tests
Integration tests are located in src/services/directory-services/gsuite-directory.service.integration.spec.ts.
Test Coverage:
- Basic sync (users and groups)
- Sync with filters
- Users-only sync
- Groups-only sync
- User filtering scenarios
- Group filtering scenarios
- Disabled users handling
- Group membership scenarios
- Error handling
Running Integration Tests:
Integration tests require live Google Workspace credentials:
-
Obtain test credentials from the Bitwarden shared collection
-
Create a
.envfile in theutils/folder with:GOOGLE_ADMIN_USER=admin@example.com GOOGLE_CLIENT_EMAIL=service-account@project.iam.gserviceaccount.com GOOGLE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n" GOOGLE_DOMAIN=example.com -
Run tests:
# Run all integration tests (includes LDAP, Google Workspace, etc.) npm run test:integration # Run only Google Workspace integration tests npx jest gsuite-directory.service.integration.spec.ts
Test Data:
The integration tests expect specific test data in Google Workspace:
-
Users: 5 test users in organizational unit
/Integration testing- testuser1@bwrox.dev (in Group A)
- testuser2@bwrox.dev (in Groups A & B)
- testuser3@bwrox.dev (in Group B)
- testuser4@bwrox.dev (no groups)
- testuser5@bwrox.dev (disabled)
-
Groups: 2 test groups with name pattern
Integration*- Integration Test Group A
- Integration Test Group B
API Reference
Google Admin SDK APIs Used
-
Users API:
admin.users.list() -
Groups API:
admin.groups.list() -
Members API:
admin.members.list()
Rate Limits
Google Workspace Admin SDK has rate limits:
- Default: 1,500 queries per 100 seconds per user
The service does not implement rate limiting logic; it relies on API error responses.