Invalidate cached credentials on auth failures - #3777
Merged
alexgromero merged 2 commits intoAug 26, 2026
Merged
Conversation
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## feature/credential-refresh #3777 +/- ##
=============================================================
Coverage ? 92.57%
=============================================================
Files ? 68
Lines ? 16117
Branches ? 0
=============================================================
Hits ? 14920
Misses ? 1197
Partials ? 0 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
alexgromero
force-pushed
the
feature/credential-refresh
branch
from
August 15, 2026 19:35
f86a614 to
34909c6
Compare
alexgromero
force-pushed
the
cred-refresh/invalidation
branch
from
August 15, 2026 20:47
a35ec5e to
de6a165
Compare
alexgromero
force-pushed
the
cred-refresh/invalidation
branch
from
August 21, 2026 20:13
de6a165 to
3c9a5a4
Compare
ubaskota
reviewed
Aug 23, 2026
ubaskota
left a comment
Contributor
There was a problem hiding this comment.
It looks good to me as is. I've added a comment to point out a test gap and will approve it after its addressed. Thanks
| fetcher.refresh_credentials() | ||
|
|
||
|
|
||
| class TestInvalidate: |
Contributor
There was a problem hiding this comment.
Can we add a test for the case where the refresh lock is already held when _invalidate is called?
ubaskota
approved these changes
Aug 26, 2026
alexgromero
merged commit Aug 26, 2026
2577d8d
into
boto:feature/credential-refresh
44 checks passed
alexgromero
added a commit
that referenced
this pull request
Aug 26, 2026
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.
Issue #, if available:
Python-9269
Overview
This updates credential refresh to invalidate cached refreshable credentials after service authentication failures.
When
DEFAULT_NEW_CREDENTIAL_REFRESHis enabled, a service can reject otherwise unexpired credentials withExpiredTokenorInvalidToken, but botocore may still keep that credential set cached until its normal expiration time. This change marks the rejected credentials stale so the next request goes back through refresh instead of continuing to reuse the rejected credentials.The legacy refresh path is unchanged.
What changed
On the signing side,
RequestSignernow records the access key that signed the request inrequest.context. This is only done for the standard credential-chain case; request-scoped credentials and identity-cache flows are intentionally excluded.On the response side, a new
after-callhandler watches forExpiredTokenandInvalidToken. When one of those errors is returned, it resolves the client's current credentials and invalidates them only if the cached access key still matches the access key that signed the rejected request. That avoids mutating fresh credentials when another thread has already completed a refresh.The invalidation itself sets the cached credentials' expiry to
now, so the next credential lookup routes through refresh. It also uses a non-blocking acquire on the refresh lock: if a refresh or another invalidation is already in progress, it returns immediately instead of blocking.For providers with an intermediate cache layer, invalidating only the outer
RefreshableCredentialsobject is not enough. AssumeRole, AssumeRoleWithWebIdentity, and SSO can otherwise refresh back into the same cached provider result. This change wires those providers to also expire the matching cached provider entry so the next refresh goes back to the underlying source.Testing
Added coverage for:
signing_access_keyand skips request-scoped / identity-cache caseserror_code_overrideBy submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.