feat: Add reactive token refresh on 401/403 API responses
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
- Issue type
- Feature
- Clarity
- Needs clarification
- Activity status
- Stale
- Tech stack
- python
- Domain
- api, authentication, backend
Research direction
Start by reading the existing error mapping in airbyte_cdk/sources/streams/http/error_handlers/default_error_mapping.py, then trace token handling through abstract_oauth.py, http_client.py, and the declarative HttpRequester. Define how 401 and token-expiry 403 responses are identified and how refresh and retry interact with existing failures; the work is done when the behavior is covered for successful refresh, failed refresh, and a still-failing retry.
Written by the indexing model from the issue text.
Description
Summary
When an API returns a 401 or 403 error indicating an expired token, the connector should automatically refresh the token and retry the request. Currently, the CDK only performs proactive token refresh (checking expiry before requests) but does not handle reactive refresh when the API itself rejects the token.
Problem
A user reported a 403 error from the Amazon Selling Partner connector:
'GET' request to 'https://sellingpartnerapi-na.amazon.com/reports/2021-06-30/reports/521059020455'
failed with status code '403' and error message: 'Access to requested resource is denied.'.
Response: {'errors': [{'code': 'Unauthorized', 'message': 'Access to requested resource is denied.',
'details': 'The access token you provided has expired.'}]}
The connector has OAuth configured and the CDK's AbstractOauth2Authenticator.get_access_token() method does check token_has_expired() before each request. However, when the API returns a 403 "token expired" error (rather than the proactive check catching it), the connector fails immediately.
Root Cause Analysis
-
Current behavior: The CDK's
default_error_mapping.pytreats both 401 and 403 asResponseAction.FAIL:401: ErrorResolution( response_action=ResponseAction.FAIL, failure_type=FailureType.config_error, error_message="HTTP Status Code: 401. Error: Unauthorized...", ), 403: ErrorResolution( response_action=ResponseAction.FAIL, failure_type=FailureType.config_error, error_message="HTTP Status Code: 403. Error: Forbidden...", ), -
Existing retry logic: The CDK (v0.30.0) added retry logic for token refresh requests on 429, 500, 502, 504 errors. However, this is for the token refresh endpoint, not for API calls that return auth errors.
-
Why this happens:
- Amazon LWA access tokens are valid for ~1 hour
- Long-running syncs can exceed this duration
- Clock skew between Airbyte and the API can cause early expiration
- The proactive check relies on tracking expiry time internally, which may not match the API's actual token validity
Proposed Solution
Add reactive token refresh capability that:
- Detects auth-related errors (401, or 403 with specific error messages like "token expired")
- Attempts to refresh the access token
- Retries the failed request with the new token
- Falls back to failure if refresh fails or retry still fails
This could be implemented as:
- A configurable option in the authenticator to specify which status codes/error patterns should trigger refresh
- Integration with the existing
ErrorHandlerto intercept auth errors before failing - A retry decorator or middleware in the HTTP client
Affected Components
airbyte_cdk/sources/streams/http/error_handlers/default_error_mapping.pyairbyte_cdk/sources/streams/http/requests_native_auth/abstract_oauth.pyairbyte_cdk/sources/streams/http/http_client.py- Declarative framework's
HttpRequesterand error handling
Related
- CDK v0.30.0 added "OAuth: retry refresh access token requests" for transient errors on the token endpoint
- This issue is about retrying API calls when they return auth errors
Context
- Devin session: https://app.devin.ai/sessions/e49a02f10e9940fabfaee7782dc938e6
- Reported by: [email protected]
- Affected connector: source-amazon-seller-partner (but applies to all OAuth connectors)
- Dominant language
- Python
- Stars
- 27
- Forks
- 56
- Avg merge
- 3d 18h
- Merged PRs (30d)
- 30
Getting set up
- Ships a Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from airbytehq/airbyte-python-cdk
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
airbytehq/airbyte-python-cdk#1080 ·
Maintainers usually reply within 1 day
-
community
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
airbytehq/airbyte-python-cdk#782 ·
Maintainers usually reply within 1 day
-
community
Difficulty 5/5 Over a week Newbie friendliness 35/100
airbytehq/airbyte-python-cdk#1148 · 1 comment ·
Maintainers usually reply within 1 day
-
community
Difficulty 2/5 1-3 hours Newbie friendliness 45/100
airbytehq/airbyte-python-cdk#1146 · 1 comment · 3 reactions ·
Maintainers usually reply within 1 day
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 48/100
airbytehq/airbyte-python-cdk#1120 · 2 comments ·
Maintainers usually reply within 1 day
All issues in airbytehq/airbyte-python-cdk
Similar issues
-
documentation good first issue
Difficulty 2/5 Half a day Newbie friendliness 72/100
sujithputta02/Esapay#13 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
Maintainers usually reply within 1 day
-
needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
gke-labs/kube-agents#3277 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
jbacalso24/mimry#291 ·
Maintainers usually reply within 1 day
-
good first issue
Difficulty 2/5 Under an hour Newbie friendliness 82/100
eli-alvarado/us-watchlist-alerts#14 ·
Maintainers usually reply within 1 day