Work identity: acquire and hold the enterprise identity assertion - #1760
Draft
RhysSullivan wants to merge 4 commits into
Draft
Work identity: acquire and hold the enterprise identity assertion#1760RhysSullivan wants to merge 4 commits into
RhysSullivan wants to merge 4 commits into
Conversation
oauth.start required the caller to supply the identity assertion, and nothing in the product could obtain one: the IdP client's secret is server-side, so a browser could not reach the profile at all. Whatever was passed also became the connection's renewal credential, so an ID token made every renewal past its first hour fail needs-SSO. Link the identity once per (owner, IdP app) instead. The link runs the IdP app's own authorization-code flow through the existing OAuth machinery -- one oauth_session row, buildAuthorizationUrl, exchangeAuthorizationCode, the shared callback -- redeems the code server-side, and takes custody of the REFRESH token (id-jag draft 4.5), falling back to recorded ID-token custody with its deadline when the IdP issues none. oauth.start's subjectToken is now optional: omitted, it resolves the held identity and points the connection's refresh slot at the shared record rather than copying it. An explicit assertion keeps its private copy and behaves exactly as before.
The renewal path treated every rejected subject the same: mark the connection dead and demand a reconnect. For a shared work identity that is wrong twice over -- the connection lost nothing, and reconnecting N of them fixes nothing one re-link would not. Record the rejection on the identity record instead, so every connection behind it short-circuits before spending its own doomed exchange, and surface it as workIdentityRelinkRequired. Connections get health only, never the reauth stamp that a reconnect alone clears, so the next resolve after a re-link succeeds untouched.
Four routes next to the existing oauth ones: start, complete, a status a console polls, and unlink. The status is the browser-facing projection of a credential record, so it carries the account and the custody kind and nothing that could stand in for the token. Both browser flows land on the one callback URL an enterprise registers, so the callback route now asks the in-flight session which flow came back rather than inferring from the URL. A connection's popup payload is unchanged; a link's is spread under its own key, since the two objects share field names.
A selfhost scenario runs the whole thing through the product: link via a real OIDC sign-in, connect with no subjectToken in the payload, call a tool. Both emulator ledgers carry the proof -- the sign-in, executor's own code redemption, the exchange and the redemption -- and the MCP server sees no authorize request. Renewal past ID-token expiry is not asserted here: the Okta emulator's token lifetimes are compiled-in constants with no seed knob to compress them. That claim is proven hermetically in the SDK suite instead.
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-cloud | 2b6b7ed | Aug 26 2026, 11:45 PM |
Deploying with
|
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs |
executor-marketing | 2b6b7ed | Commit Preview URL Branch Preview URL |
Aug 26 2026, 11:44 PM |
Contributor
Cloudflare preview
Sign-in is Cloudflare Access (one-time PIN to an allowed email). The preview has its own database and encryption key; it is destroyed when this PR closes. |
@executor-js/cli
@executor-js/config
@executor-js/execution
@executor-js/sdk
@executor-js/codemode-core
@executor-js/runtime-quickjs
@executor-js/plugin-file-secrets
@executor-js/plugin-graphql
@executor-js/plugin-keychain
@executor-js/plugin-mcp
@executor-js/plugin-onepassword
@executor-js/plugin-openapi
executor
commit: |
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.
Adds the missing front door for enterprise-managed authorization: a per-user work-identity link (server-side authorization-code exchange against the org's registered IdP client) with refresh-token custody in the credential provider, oauth.start resolving the held identity when the payload omits subjectToken, and a work-identity-dead state distinct from connection-dead so one re-link recovers every managed connection. Explicit-subjectToken callers are unchanged. The rollout gate is consulted exactly once per connect and never by the link flow, pinned by tests.