Report #76403
[bug\_fix] AWS STS AssumeRole returns ExpiredToken or RequestExpired when attempting to assume a second role using temporary credentials from a first assumed role \(role chaining\)
When assuming the first role \(RoleA\) using long-term credentials \(or initial STS\), explicitly set DurationSeconds to 3600 \(1 hour\) or less. When assuming the second role \(RoleB\) using the temporary credentials from RoleA, ensure the requested DurationSeconds is less than or equal to the remaining lifetime of the RoleA credentials, and never exceed 3600 seconds \(1 hour\) for any chained role assumption. Root cause: AWS IAM enforces that when you assume a role using temporary security credentials \(role chaining\), the maximum session duration is capped at 1 hour, regardless of the role's MaximumSessionDuration setting \(which could be 12 hours\). Additionally, you cannot request a duration for RoleB that exceeds the remaining time on the RoleA credentials.
Journey Context:
Developer needs to deploy an artifact from their dev account to a production account via a shared-services account for auditing. They write a deployment script. Step 1: Using their dev IAM user long-term credentials, they call \`aws sts assume-role\` to assume a role in the SharedServices account \(RoleA\), requesting the default duration \(1 hour\). This succeeds and returns temporary credentials \(CredsA\). Step 2: Using CredsA \(exported to env vars\), they immediately call \`aws sts assume-role\` again to assume the deployment role in the Production account \(RoleB\), requesting a 12-hour duration \(since they expect a long deployment\). This call fails immediately with \\"The security token included in the request is expired\\" or \\"DurationSeconds exceeds the 1 hour limit for role chaining\\". The developer checks their system clock \(synchronized\). They verify that CredsA are indeed fresh \(just created\). They check the Production role's trust policy \(correctly trusts SharedServices role\). They realize that role chaining has a 1-hour maximum duration limit. They change the script to request only 3600 seconds for RoleB, and it succeeds. They also realize that if they wait 30 minutes before assuming RoleB, they must request DurationSeconds of 3300 or less to fit within RoleA's remaining lifetime.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-21T10:49:55.875070+00:00— report_created — created