feat(source-salesforce): persist rotated refresh token (RTR support)#80892
feat(source-salesforce): persist rotated refresh token (RTR support)#80892James Truty (jtruty) wants to merge 3 commits into
Conversation
Salesforce is mandating OAuth Refresh Token Rotation. With RTR enabled on the connected app, each refresh_token exchange returns a new single-use refresh token and invalidates the previous one. The connector discarded the returned token, so the next sync used an invalidated token and the grant was revoked. Capture the rotated refresh token in Salesforce.login() and persist it via a CONNECTOR_CONFIG control message emitted from the _get_sf_object chokepoint, covering check, discover, and read. The path is a strict no-op when RTR is off, since Salesforce returns a new refresh token only when rotation is enabled, so the change is non-breaking. Closes airbytehq#80783 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fx2eMxCQoDZfL6NUdS4cc5
|
Note 📝 PR Converted to Draft More info...Thank you for creating this PR. As a policy to protect our engineers' time, Airbyte requires all PRs to be created first in draft status. Your PR has been automatically converted to draft status in respect for this policy. As soon as your PR is ready for formal review, you can proceed to convert the PR to "ready for review" status by clicking the "Ready for review" button at the bottom of the PR page. To skip draft status in future PRs, please include |
👋 Welcome to Airbyte!Thank you for your contribution from jtruty/airbyte! We're excited to have you in the Airbyte community. If you have any questions, feel free to ask in the PR comments or join our Slack community. 💡 Show Tips and TricksPR Slash CommandsAs needed or by request, Airbyte Maintainers can execute the following slash commands on your PR:
Tips for Working with CI
📚 Show Repo GuidanceHelpful Resources
|
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fx2eMxCQoDZfL6NUdS4cc5
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Fx2eMxCQoDZfL6NUdS4cc5
What
Adds support for Salesforce OAuth Refresh Token Rotation (RTR) to
source-salesforce.Closes #80783
Why
Salesforce is mandating RTR as a security control. With RTR enabled on the connected app, each
grant_type=refresh_tokenexchange returns a new, single-use refresh token and invalidates the previous one. The connector discarded the refresh token in the login response, so once RTR is enabled the next sync authenticates with an invalidated token and Salesforce revokes the grant, breaking the connection until manual re-auth.How
Salesforce.login()now captures the refresh token from the token response when one is present.SourceSalesforce._persist_rotated_refresh_tokenwrites the rotated token back into the connector config and emits aCONNECTOR_CONFIGcontrol message. It runs from the single_get_sf_objectchokepoint, so it coverscheck,discover, andread.CONNECTOR_CONFIGcontrol messages for all three operations, double-gated on the config actually changing, so the rotated token survives across syncs.This is non-breaking: Salesforce returns a new
refresh_tokenonly when rotation is enabled, so for connections without RTR the new path is a strict no-op and behavior is unchanged. No spec change and no new config option.Testing
poetry run pytest unit_tests/passes (111 tests). New unit tests cover:Known limitations
RTR's single-use semantics mean a refresh token can still be lost in two edge cases that are not addressed in connector code:
checkand sync on the same source can race two rotations.Both are mitigated by configuring a refresh token rotation grace window on the Salesforce connected app.