Skip to content

Add web identity token credential resolvers and providers - #126

Merged
ubaskota merged 2 commits into
developfrom
web_identity_token_impl
Nov 12, 2026
Merged

ubaskota merged 2 commits into
developfrom
web_identity_token_impl

Conversation

@ubaskota

Copy link
Copy Markdown
Contributor

Issue #, if available:

Description of changes:

  • WebIdentityCredentialsResolver / AsyncWebIdentityCredentialsResolver: read the OIDC token file before each refresh, call STS unsigned, cache the credentials, and retry ExpiredTokenException (re-reading the token) and IDPCommunicationError.
  • WebIdentityTokenEnvProvider / ProfileWebIdentityProvider (plus Async* versions), registered for the default chain: configured by AWS_WEB_IDENTITY_TOKEN_FILE + AWS_ROLE_ARN, or by a profile's web_identity_token_file + role_arn.
  • The AssumeRole provider no longer claims profiles that set role_arn + web_identity_token_file without source_profile/credential_source.
  • The internal STS client uses NoAuthResolver() and a placeholder credentials resolver, so it never builds its own credential chain.

Testing

  • Unit tests (tests/unit/test_web_identity.py, test_assume_role.py) cover sync and async: request building, the SEP retry rules, unreadable/empty token files, caching and invalidation, concurrency, the providers, routing, and a default-chain test using the real STS client over a mock transport that asserts the request is unsigned.
  • make static-analysis, make aio-check and make test-unit pass for packages/aws-credentials-sts
  • Tested manually end to end against a Cognito identity pool:
    1. Created a Cognito identity pool and an IAM role that trusts only AssumeRoleWithWebIdentity from that pool.
    2. Got an OIDC token with cognito-identity get-open-id-token and wrote it to a file.
    3. Resolved credentials with the sync and async resolvers directly, and through the sync and async default chains via AWS_WEB_IDENTITY_TOKEN_FILE / AWS_ROLE_ARN, with no other credentials configured.
    4. Called STS GetCallerIdentity with the returned credentials. All four cases returned the web identity role's assumed-role ARN, and a corrupted token failed with InvalidIdentityTokenException.

Follow-up

A follow-up PR will add the web identity feature IDs to the providers once the smithy-python change is merged and released.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@ubaskota
ubaskota requested a review from a team as a code owner November 11, 2026 22:37
async with self._refresh_lock:
self._credentials = None

async def _assume_role_with_web_identity(self) -> AWSCredentialsIdentity:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After going through both resolvers, _call was the only part worth sharing, since it holds the SEP retry rules. I moved it into a single fetch_web_identity_credentials program in _web_identity.py, which both resolvers now run with run_program / run_program_async.

@ubaskota
ubaskota merged commit 94d5b04 into develop Nov 12, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants