feat: improve OAuth broker credential handling (labels, multi-account, reconnect, stale cleanup)#162
Open
sean-at-jentic wants to merge 30 commits intomainfrom
Open
feat: improve OAuth broker credential handling (labels, multi-account, reconnect, stale cleanup)#162sean-at-jentic wants to merge 30 commits intomainfrom
sean-at-jentic wants to merge 30 commits intomainfrom
Conversation
added 30 commits
April 2, 2026 17:58
Previously, labels were stored in oauth_broker_connect_labels at connect-link
creation time, keyed by (broker_id, external_user_id, app_slug). This meant
two connect-links for the same app (e.g. personal + work Gmail) would overwrite
each other before either OAuth flow completed.
New approach:
- Label is encoded as a query param in the success_redirect_uri passed to
Pipedream when creating the connect token.
- Pipedream redirects the user's browser to
/oauth-brokers/{id}/connect-callback?label=...&app=...&external_user_id=...
after successful OAuth.
- The callback writes the label to oauth_broker_connect_labels at that point
(one completion at a time) and immediately triggers discover_accounts() so
the credential lands before the UI loads.
- Browser is then redirected to /credentials.
Because each connect-link gets its own token and its own success_redirect_uri,
the label is tied to the specific OAuth completion event — not to a shared
app_slug slot that can be clobbered by a concurrent link.
Changes:
- pipedream.py: create_connect_token() accepts optional success_redirect_uri
- oauth_brokers.py: connect-link handler builds redirect URI + new GET
/connect-callback endpoint
- auth.py: connect-callback is public (browser redirect, no auth context)
- Add account_id to oauth_broker_accounts unique key + primary key. Old: UNIQUE(broker_id, external_user_id, api_host) — one slot per api_host, second Gmail account silently overwrote the first. New: UNIQUE(broker_id, external_user_id, api_host, account_id). - Pending label (from connect-link callback) now only applies to NEW rows. Existing accounts keep their stored label — connecting a second Gmail no longer relabels the first one. - credentials UPDATE on sync no longer touches label at all (only value/api_id). Label is set at INSERT time from pending, or preserved on subsequent syncs. - oauth_brokers list endpoint now returns label field. Migration 0002 recreates oauth_broker_accounts with new schema and migrates existing rows (rebuilding id to include account_id).
…ate for same-app accounts
…lti-account same app)
…p api_host + external_user_id
… delete (stale variable references)
…m_oauth credentials
…Auth, replaces old account after sync confirms new one
…or_toolkit) on reconnect-link endpoint
…ponent; add missing RotateCcw import
…xy sends wrong Host header)
… delete logic (revoke Pipedream + clean vault + DB)
…s spaRoute html interception)
…e /oauth-brokers API calls)
…o diagnose silent failures
…rtError was silently swallowed)
…, account_id, synced_at, OAuth badge)
… stripped by extra=ignore)
…, description, styled AppLink)
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
A batch of improvements to how Pipedream OAuth broker credentials are managed end-to-end.
Label routing via
success_redirect_uriPreviously labels were stored at connect-link creation time, keyed by
app_slug, which caused collisions when connecting multiple accounts for the same app (e.g. two Gmail accounts). Labels are now passed through Pipedream'ssuccess_redirect_uricallback, so each connection carries its own label and they cannot overwrite each other.Multi-account support (same app_slug)
Added migration
0002to includeaccount_idin theoauth_broker_accountsunique constraint and primary key — previously two Gmail accounts would collide on the same row.compose.ymlnow mountsalembic/as a volume so new migrations are picked up without an image rebuild.Reconnect button
New Reconnect button (↺) on both the OAuth Brokers page and the Credentials page. Generates a fresh connect link; on completion, the new account is confirmed in DB before the old one is deleted. Redirects back to the originating page (
/credentialsor/oauth-brokers).Stale account cleanup
discover_accounts()now tracks seen account and credential IDs during sync and deletes any rows not returned by Pipedream (revokes from Pipedream, removes vault + toolkit credential bindings).Credentials page improvements
app_slug,account_id,synced_atfor OAuth credentialsdeleteAccount(broker-aware revoke) instead of simple credential deleteOther fixes
build_absolute_urlprefersX-Forwarded-Host(fixes dev proxy sending wrongHostheader)/connect-callbackpaths from SPA HTML interceptionspa_middlewareexcludes/oauth-brokers/.../connect-callbackfrom SPA interception/oauth-brokers/.../connect-callback(browser redirect target, no auth token available)account_idas path param (notapi_host) — correct for multi-account same-appexternal_user_idremoved fromConnectLinkRequestAPI surface; derived from broker configPRs superseded
This PR supersedes #154 (fix/credential-label-resync), which was an earlier partial fix for the label issue.