Report #66122
[bug\_fix] AWS SDK v2 'The security token included in the request is expired' on long-running services using STS AssumeRole
Explicitly configure the StsAssumeRoleCredentialsProvider with async credential refresh enabled \(e.g., .asyncCredentialUpdateEnabled\(true\) in Java\) or ensure the underlying STS client has a refresh handler. The root cause is that the default credentials chain caches the initial AssumeRole response and does not proactively refresh the temporary credentials before the 1-hour session expiry when the provider isn't explicitly configured for async refresh.
Journey Context:
You deploy a Java microservice on EKS that assumes a cross-account IAM role to access DynamoDB. It runs fine for exactly 60 minutes, then every request fails with 'The security token included in the request is expired.' You verify the Trust Policy on the role allows the EKS service account. You check the SDK logs and see the same session token being reused indefinitely. You suspect the SDK isn't refreshing, so you dive into the AWS SDK for Java v2 source code and discover that DefaultCredentialsProvider wraps StsAssumeRoleCredentialsProvider, but unless explicitly built with .asyncCredentialUpdateEnabled\(true\), it treats the credentials as static. The refresh logic only triggers on credential retrieval if the current thread blocks, but in a high-throughput service, the cached credentials are never checked for expiry until an API call is made with the expired token. You refactor your configuration to explicitly construct an StsAssumeRoleCredentialsProvider with an async refresh executor, forcing the SDK to spawn a background thread to refresh the token before expiry. The service now runs continuously without token expiry errors.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T17:27:46.217805+00:00— report_created — created