fix(oauth): preserve provider error detail on refresh token failure - #1138
Draft
Anatolii Yatsuk (tolik0) wants to merge 1 commit into
Draft
fix(oauth): preserve provider error detail on refresh token failure#1138Anatolii Yatsuk (tolik0) wants to merge 1 commit into
Anatolii Yatsuk (tolik0) wants to merge 1 commit into
Conversation
When an OAuth refresh request is rejected, the CDK replaced the provider's own diagnostic with one fixed sentence. `_wrap_refresh_token_exception` already parsed the error body to decide whether the failure was a refresh token failure and then discarded it. For Microsoft Entra that body carries an AADSTS code which separates completely different root causes: AADSTS50173 (grant revoked, e.g. the user changed their password), AADSTS7000218 / AADSTS700025 (client type or secret misconfiguration) and AADSTS50076 / AADSTS50078 / AADSTS700082 (Conditional Access requiring an interactive sign-in). All of them collapsed into the same string, and no AADSTS code reached production failure summaries. The parsed body is now reused instead of being parsed a second time, the full provider response goes to `internal_message` so it lands in the logs, and a short single-line `error` / `error_description` detail is appended after the existing actionable guidance in the user-facing message. Bodies that are empty, non-JSON or not a JSON object degrade to the previous behaviour without raising. Everything surfaced is run through secret redaction, and the authenticator's own refresh token and client secret are redacted explicitly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
👋 Greetings, Airbyte Team Member!Here are some helpful tips and reminders for your convenience. 💡 Show Tips and TricksTesting This CDK VersionYou can test this version of the CDK using the following: # Run the CLI from this branch:
uvx 'git+https://github.com/airbytehq/airbyte-python-cdk.git@tolik0/oauth-preserve-provider-error-detail#egg=airbyte-python-cdk[dev]' --help
# Update a connector to use the CDK from this branch ref:
cd airbyte-integrations/connectors/source-example
poe use-cdk-branch tolik0/oauth-preserve-provider-error-detailPR Slash CommandsAirbyte Maintainers can execute the following slash commands on your PR:
|
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.
What
When an OAuth refresh request is rejected,
AbstractOauth2Authenticator._make_handled_requestraised anAirbyteTracedExceptionwhose user-facing message was one fixed sentence, and it threw away the provider's own diagnostic._wrap_refresh_token_exceptionhad already parsed the error body withexception.response.json()in order to decide whether the failure was a refresh-token failure, and then discarded that parsed body.That matters most for Microsoft Entra, where the body carries an AADSTS code that separates root causes needing completely different fixes:
AADSTS50173— the grant was revoked, typically because the user changed or reset their password. Re-authenticating is the fix.AADSTS7000218/AADSTS700025— the app registration's client type or client credential is misconfigured. Re-authenticating does not help; the app registration has to change.AADSTS50076/AADSTS50078/AADSTS700082— Conditional Access requires an interactive sign-in or MFA. Again a different fix, and one the workspace admin has to make.Today all three collapse into the same string. Across 300 sampled production failure summaries for source-bing-ads, zero contain an AADSTS code, so support has no way to tell these apart from the failure summary. See airbytehq/oncall#12835.
How
_make_handled_request, and passed into_wrap_refresh_token_exceptionthrough a new optionalresponse_contentargument, so the response is no longer parsed twice. The argument defaults toNoneand the method parses on demand when it is absent, so existing callers keep working.internal_messagecarries the full provider response (HTTP <status>: <body>, truncated at 1000 characters), so the whole payload lands in the logs.messagedeliberately keeps the existing actionable sentence as its lead: "Refresh token was rejected by the OAuth provider (invalid, expired, or already used). Re-authenticate this source's credentials in its connection settings." Only after that is a short provider detail appended, asProvider error: <error>: <error_description>, built from the standard OAuth 2.0erroranderror_descriptionfields, collapsed to a single line and truncated at 200 characters. Two hundred characters is enough to keep theAADSTS<code>and the beginning of its description, since Entra puts the code at the front oferror_description, while staying short enough that the failure summary is still readable. No raw provider blob becomes the primary message, and when the body has no usableerror/error_descriptionthe message is byte-for-byte what it was before.AttributeErroron.get(...)inside the already-failing error path.filter_secrets, and the authenticator's own refresh token and client secret are redacted explicitly on top of that, in case a provider echoes submitted credentials back in its payload. Only response bodies are read, so request headers, includingAuthorization, are never echoed.No changelog entry or version bump is included:
CONTRIBUTING.mdstates releases are drafted automatically bysemantic-pr-release-drafterfrom the PR title, and the package version is computed bypoetry-dynamic-versioning.CHANGELOG.mdis frozen and points at GitHub Release Notes.Test plan
New tests in
unit_tests/sources/streams/http/requests_native_auth/test_requests_native_auth.py:internal_messagewhilemessagestill starts with the re-authenticate guidance and then carries the provider code on a single line;error_description;RequestExceptioninstead of raising something new;error/error_description, asserting the user-facing message is exactly the unchanged sentence.The existing
test_refresh_access_token_wrappedassertion onmessagewas relaxed from equality tostartswith, since the wrapped case now appendsProvider error: invalid_grant.This repo is Poetry-managed, so
uv run pytestcannot resolve the dev dependencies; the tests were run with the project's Poetry virtualenv:🤖 Generated with Claude Code