Repository navigation
fix(oauth): resolve the app client secret at refresh time, not from the stored copy (#13630) - #13757
Merged
Merged
Conversation
Contributor
✅ SSOT Configuration Compliance: Passing🎉 No hardcoded values detected that have SSOT config equivalents! |
# Conflicts: # autobot-backend/knowledge/connectors/tests/test_credential_store.py
Applied Black, isort, and autoflake to match code-quality checks. Triggered by workflow auto-fix-formatting.yml.
4 tasks
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.
Thinking Path
_oauth_bundle()copies the OAuth appclient_id/client_secret— operator-owned, one per provider — into every user's credential bundle, andget_access_tokenrefreshed from that copy.The copy is a snapshot taken when the user connected, and nothing rewrites it. So rotating the app secret silently strands every existing connection: refresh keeps presenting the retired secret and starts failing at the next refresh, not at rotation time.
oauth_flow.resolve_client_credentials(provider)already resolves app credentials from operator config. The refresh path simply wasn't using it.What Changed
_resolve_app_credentials(creds)prefers the operator's current app config and falls back to the stored copy when the provider is unknown or unconfigured.That fallback is what makes this safe to land alone: no migration, and it cannot make a working credential worse. A bundle whose provider was since removed from config keeps refreshing exactly as it does today. Rotation starts working immediately for every credential whose provider is still configured — including ones stored long before this change.
Deliberately not in this PR — #13630 stays open
The issue's full scope is larger and the rest is not safe to do unprompted:
OAuthProviderwith the declarative deviation fields (separate refresh URL,tokenEndpointAuthMethod, form-vs-JSON, per-grant field renames, response envelopes, scope separator). All optional and cheap, but adding fields no provider currently needs is speculative until one does — worth doing when the first real provider forces it, which is exactly when the shape will be known.Verification
Mutation-checked — reverting to the stored snapshot must fail the rotation test:
..._rotated_app_secret_is_used......_unknown_provider_falls_back......_bundle_without_a_provider......_unconfigured_provider_falls_back...Model Used
Opus 5
Part of #13630