Repository navigation
feat(credentials): keyless Google Workspace domain-wide delegation via IAM signJwt - #9933
Merged
Merged
Conversation
A keyless (workload identity federation) google-service-account credential
can now opt into domain-wide delegation with an optional `delegation`
({ user, services }) in its keyless configuration. Runs for a delegated
Workspace service (Gmail, Drive, Docs, Sheets, Calendar) exchange Sim's
token at STS, have IAM signJwt the JWT-bearer assertion for the service
account with sub set to the delegated user, and exchange it at
oauth2.googleapis.com/token. The credential acts only as its own user: a
different Impersonated Account is refused before Google is contacted.
Saving a delegated credential mints a delegated token per service and makes
one cheap read as the user; the stray-subject pin probe also checks signJwt.
Tokens are cached per credential, secret version, delegated user, and scopes.
Credentials saved without delegation store exactly the same secret and
resolve exactly as before; BigQuery and Vertex AI keep the service account
token path.
…e service account dialog The Gmail, Google Drive, Google Docs, Google Sheets, and Google Calendar integrations now offer the keyless (Workload Identity Federation) mode, with a Domain-wide delegation picker preselecting the service the dialog was opened for and a required Workspace user. The dialog lists the scopes to authorize in the Admin console, and its gcloud commands grant roles/iam.serviceAccountTokenCreator (which includes signJwt) instead of roles/iam.workloadIdentityUser when delegation is on. Other Workspace services keep the JSON key only.
…copes A keyless credential with domain-wide delegation now signs an assertion only for the scopes its delegated services authorize, and refuses any other scope before contacting Google (a Gmail read-only connector, the admin directory scopes, cloud-platform). A requested read-only scope is minted as the authorized read-write scope that covers it, so the Drive file picker works for a credential delegated for Drive, Docs, or Sheets. The delegated assertion is exchanged through the same transport a JSON key uses (bounded read, retries on 429 and 5xx within a budget), sharing its list of diagnostic error codes. Saving checks Drive, Docs, and Sheets, which share scopes and a read, once, and the pin probe signs for every delegated scope. A stored secret naming a delegated service a later release adds stays readable: that service authorizes nothing here, and Google Cloud tokens and the known services keep working. An unreadable secret fails in the shared service-account codes.
…econnect Preparing a reconnect of a keyless Google credential now returns its stored Workspace user and delegated services to the credential's admin (neither is secret), and the dialog opens on them, adding the service it was opened for. Reconnecting no longer silently drops delegation. A dialog opened for a delegable service requires that service to be delegated.
… for keyless delegation A read-only Gmail request is minted as the authorized gmail.modify scope, an Impersonated Account is compared trimmed, and each documented token-endpoint refusal gets its own copy instead of always pointing at the Admin console. The stored secret is parsed in one place and the save-time read shares the POST helper's redirect and timeout guards.
… map The prepare use case no longer branches on the Google provider: each provider's reader returns everything a reconnect reopens on. The dialog takes the stored delegation type from the contract, and one helper says which services a keyless Google credential serves.
…ns page and chat card Both entry points pass the OAuth provider id (google-email) where the dialog compared against service ids (gmail), so Gmail never offered keyless mode there and a keyless reconnect from chat was refused. The shared helpers and the dialog now map either id through googleDelegationServiceFor.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
[High impact] The PR appears safe to merge; the latest change fixes the previous documentation finding. SummaryAdds keyless Google Workspace delegation through IAM
|
Contributor
There was a problem hiding this comment.
1 issue found across 17 files
Confidence score: 3/5
- The scope matcher in
apps/sim/lib/credentials/google-workload-identity.server.tsrejects every Calendar token because credentials authorizecalendarwhile the connector requestscalendar.events.readonly. Add an explicit mapping for the read-only scope.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/sim/lib/credentials/google-workload-identity.server.ts">
<violation number="1" location="apps/sim/lib/credentials/google-workload-identity.server.ts:846">
P2: Calendar credentials authorize `calendar`, but the connector requests `calendar.events.readonly`; this matcher finds neither `calendar` nor a mapping and rejects every such token. Map this read-only scope to the authorized `calendar` scope.</violation>
</file>
…d calendar.events.readonly The Calendar connector requests calendar.events.readonly, whose read-write sibling calendar.events is not what a Calendar delegation authorizes, so every keyless delegated Calendar connector token was refused. Map it to calendar, the authorized scope Google documents as covering it.
Collaborator
Author
Collaborator
Author
|
@cubic-dev-ai review this PR |
Contributor
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
…ope is served keylessly
Collaborator
Author
Collaborator
Author
|
@cubic-dev-ai review this PR |
Contributor
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
signJwt(sub = the Workspace user) → jwt-bearer exchange atoauth2.googleapis.com/token.delegation: { user, services }in the keyless config. The credential acts only as its stored user. A run that sets a different Impersonated Account is refused before Google is contacted (the comparison ignores case and surrounding spaces).drive.readonly→drive, for the Drive picker), orgmail.modifyforgmail.readonly(the Gmail label picker and the knowledge base connector).signJwtis refused. Token-endpoint refusals get copy for each of Google's documented error codes: Admin-console authorization forunauthorized_clientandaccess_denied, admin policy, a disabled or deleted service account, and neutral copy for anything else.gmail); the other two pass the OAuth provider id (google-email), and both are accepted. It lists the scopes to authorize in the Admin console, and its gcloud commands switch toroles/iam.serviceAccountTokenCreator, becauseroles/iam.workloadIdentityUserlacksiam.serviceAccounts.signJwt. A reconnect keeps the stored delegation, read through the per-provider reconnect map with no provider branch in the shared use case.error, bounded read, retry budget).Product update (if relevant)
Workspace admins can connect Gmail, Drive, Docs, Sheets and Calendar to one Workspace user without creating a service account key, which Google's DWD best practices recommend. Docs: Google service account → keyless domain-wide delegation.
Type of Change
Testing
google-email, from the Integrations page and the chat card)resolveGoogleWorkloadIdentityToken/delegatedMintScopes.Checklist