fix(credentials): authorize shared credentials without requiring a workflow - #6571
Conversation
…rkflow `authorizeCredentialUse` could only reach its member-based sharing branch when a `workflowId` was supplied, so non-workflow surfaces — knowledge base connectors, credential management — fell through to an owner-only path and rejected everyone but the user who ran the OAuth flow. A workflow now only pins which workspace a legacy account id resolves through; it never grants access on its own. Access itself is decided by one rule everywhere: active credential member, or derived credential admin. - resolve legacy account ids through whichever workspace credential rows the caller can reach, instead of an owner-only fallback - extract `canUseCredential` and replace the predicate hand-inlined at five sites - reuse `resolveCredentialTokenIdentity` for owner resolution instead of a second local copy of the same invariant - keep the workflow-pinned path from crossing a workspace boundary
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
PR SummaryHigh Risk Overview Access is now one rule everywhere: active credential member or derived credential admin. A Also extracts Reviewed by Cursor Bugbot for commit 5f6bb43. Configure here. |
Greptile SummaryThe PR centralizes credential-use authorization and permits shared OAuth credentials to resolve without a workflow while preserving workflow workspace pinning and owner-only access for unshared legacy accounts.
Confidence Score: 5/5The PR appears safe to merge, with workflow boundaries, workspace access, credential membership, derived administration, and OAuth owner validation preserved. The refactor consolidates existing credential-use checks and adds non-workflow shared-credential resolution without exposing an unsupported owner fallback or changing the resolved OAuth token identity.
|
| Filename | Overview |
|---|---|
| apps/sim/lib/auth/credential-access.ts | Refactors credential authorization around canonical actor context and token identity resolution, adding accessible-workspace lookup for legacy account IDs without weakening workflow pinning. |
| apps/sim/lib/credentials/access.ts | Adds a focused credential-use predicate that preserves the existing workspace-access and active-member-or-admin rule. |
| apps/sim/lib/auth/credential-access.test.ts | Adds coverage for shared admins and members, workspace-access loss, workflow confinement, owner fallback, and unshared legacy accounts. |
| apps/sim/executor/utils/vertex-credential.ts | Replaces a duplicated authorization condition with the shared predicate without changing behavior. |
| apps/sim/app/api/auth/oauth/credentials/route.ts | Applies the shared credential-use predicate to OAuth credential listing paths. |
| apps/sim/app/api/credentials/[id]/route.ts | Applies the shared credential-use predicate when retrieving an individual credential. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Credential-use request] --> B{Credential ID matches workspace credential?}
B -->|Yes| C{Workflow pins another workspace?}
C -->|Yes| X[Deny]
C -->|No| D{Workspace access and member or admin?}
D -->|No| X
D -->|Yes| E{Credential type}
E -->|Service account| F[Authorize workspace credential]
E -->|OAuth| G[Resolve canonical token owner]
G --> H{Owner retains workspace access?}
H -->|No| X
H -->|Yes| I[Authorize OAuth account]
B -->|No: legacy account ID| J[Find wrapping OAuth credential rows]
J --> K{Workflow supplied?}
K -->|Yes| L[Restrict rows to workflow workspace]
K -->|No| M[Consider all caller-reachable rows]
L --> N{Usable row and valid token identity?}
M --> N
N -->|Yes| I
N -->|No, workflow pinned| X
N -->|No workflow and no usable row| O{Caller owns raw account?}
O -->|Yes| I
O -->|No| X
Reviews (1): Last reviewed commit: "fix(credentials): authorize shared crede..." | Re-trigger Greptile
Summary
authorizeCredentialUsecould only reach its member-based sharing branch when aworkflowIdwas supplied, so non-workflow surfaces (KB connectors, credential management) fell through to an owner-only path and rejected everyone but the user who ran the OAuth flowaccount.ids resolve through whichever workspacecredentialrows the caller can actually reach, instead of owner-onlycanUseCredentialand replaced the predicate that was hand-inlined at five sitesresolveCredentialTokenIdentityfor owner resolution instead of keeping a second local copy of the same invariantReported against RI - MDS: a workspace admin who did not run the SharePoint OAuth flow got
Credential not foundsetting up a KB connector. The literal error came from the prod-only owner-scopedgetCredential(…, auth.userId)in the connector-create route, which staging already replaced in #5273 — this PR fixes the systemic half underneath it.Net effect: access is now decided by one rule everywhere — active credential member, or derived credential admin (workspace admin, for shared types). Membership stays explicit; a plain workspace member still needs a grant, same as in workflows.
Type of Change
Testing
New
lib/auth/credential-access.test.ts(13 cases) covering the non-owner admin/member paths, workspace-loss on both requester and owner, the workflow-pinning invariant, and the unshared-account-stays-private case. Each guard test verified to fail against the pre-fix behavior. Full suites green acrosslib/auth,lib/credentials,lib/oauth,lib/knowledge,app/api/auth,app/api/credentials,app/api/knowledge,app/api/tools,executor.Checklist