---
cuppy_hub: aws
cuppy_path: reference/sts/assume-role.md
cuppy_section: docs
cuppy_doc: H09T-EQXW
cuppy_doc_uuid: f27def79-a85d-4b0c-a152-d1343b44fb1a
cuppy_permalink: https://cuppy.io/aws/d/H09T-EQXW
cuppy_version: 4
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/aws/docs/reference/sts/assume-role
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: d45b32ce74a7edb9e8d37bc910c22e6954a264e2a384b5be2849620bacb324ef
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# AssumeRole

**What it does:** exchanges the caller's credentials for temporary credentials (access key ID, secret access key, session token) that act as the target role. The new session has the role's permissions, narrowed by any session policies you pass. It works within one account and across accounts.

**Before you call it, two things must be true:**
1. The role's **trust policy** names the caller (or the caller's account) as a principal allowed `sts:AssumeRole`, and any trust-policy conditions (MFA, external ID, source identity) are met.
2. For a **cross-account** call, the caller's own identity policy allows `sts:AssumeRole` on the role ARN. Within one account, the trust policy alone is enough when it names the caller directly.

## The request

### CLI

```
aws sts assume-role \
  --role-arn arn:aws:iam::<account-id>:role/<role-name> \
  --role-session-name <session-name> \
  --duration-seconds 3600
```

Optional: `--external-id <id>`, `--serial-number <mfa-device-arn> --token-code <6 digits>`, `--policy file://session-policy.json`, `--policy-arns arn=<policy-arn>`, `--tags Key=<k>,Value=<v>`, `--transitive-tag-keys <k>`, `--source-identity <id>`.

### TypeScript, AWS SDK for JavaScript v3

```ts
import { STSClient, AssumeRoleCommand } from "@aws-sdk/client-sts";

const sts = new STSClient({ region: "<region>" });

const { Credentials, AssumedRoleUser } = await sts.send(
  new AssumeRoleCommand({
    RoleArn: "arn:aws:iam::<account-id>:role/<role-name>",
    RoleSessionName: "<session-name>",
    DurationSeconds: 3600,
    // ExternalId: "<id>",
    // SerialNumber: "<mfa-device-arn>", TokenCode: "<6 digits>",
    // Policy: JSON.stringify(sessionPolicy),
    // PolicyArns: [{ arn: "<policy-arn>" }],
    // Tags: [{ Key: "<k>", Value: "<v>" }],
    // SourceIdentity: "<id>",
  }),
);
// Credentials: { AccessKeyId, SecretAccessKey, SessionToken, Expiration }
```

To use the role from code without handling credentials yourself, configure a profile with `role_arn` and `source_profile` and let the SDK's provider chain assume it and refresh it; see `reference/sts/credential-sources.md`.

### Raw API (query protocol)

```
POST https://sts.<region>.amazonaws.com/
Action=AssumeRole&Version=2011-06-15
&RoleArn=arn:aws:iam::<account-id>:role/<role-name>
&RoleSessionName=<session-name>
&DurationSeconds=3600
```

The request must be signed like any AWS API request; hand-signing is a known source of denials. Prefer the SDK.

## Parameters that make it fail

| Parameter | Contract | Fails when |
|---|---|---|
| `RoleArn` | required | the role does not exist, or the trust policy does not allow the caller |
| `RoleSessionName` | required, 2–64 chars, letters, digits and `+=,.@-` | outside that length or character set |
| `DurationSeconds` | 900–43200, default 3600 | above the role's maximum session duration (1–12 hours, set on the role), or above 3600 when **role chaining** (assuming a role with credentials from another role) |
| `ExternalId` | 2–1224 chars, letters, digits and `+=,.@:/-` | missing or wrong when the trust policy requires `sts:ExternalId` |
| `SerialNumber` + `TokenCode` | `TokenCode` is six digits | missing or expired when the trust policy requires MFA — the call returns access denied |
| `Policy` | one inline JSON session policy | invalid JSON or grammar (`MalformedPolicyDocument`) |
| `PolicyArns` | up to 10 managed policy ARNs in the role's account | together with `Policy`, the plaintext exceeds 2,048 characters |
| `Tags` | up to 50; key ≤ 128 chars, value ≤ 256 | a key repeats an inherited transitive tag; or the packed token is too large (`PackedPolicyTooLarge`) |
| `SourceIdentity` | 2–64 chars, cannot start with `aws:` | the trust policy requires `sts:SourceIdentity` and it is missing |

Error codes and their fixes: `reference/sts/errors.md`. A trust-policy refusal reads `… is not authorized to perform: sts:AssumeRole … because no role trust policy allows …`: see `reference/iam/errors.md`.

## What it changes

- **Creates no resource** and changes no policy. It issues credentials that stay valid until `Expiration`; there is no AssumeRole parameter to end them early (revoking sessions from the role side is not covered here).
- **Is visible to the role's owner.** The `RoleSessionName` appears in the assumed-role ARN (`arn:aws:sts::<account-id>:assumed-role/<role-name>/<session-name>`) and in the role owner's CloudTrail logs for every call made with the session. Do not put secrets or personal data in it.
- **Session permissions are fixed at issuance** to the intersection of the role's identity-based policies and the session policies you passed. Session tags override role tags with the same key (keys are case-insensitive).

## What it costs

- **Request quota.** AssumeRole shares a per-account, per-Region requests-per-second quota with `GetCallerIdentity`, `GetSessionToken`, `GetFederationToken`, `GetAccessKeyInfo` and `DecodeAuthorizationMessage`. Only the calling account's quota is consumed, not the role's account. Calls made by AWS service principals do not count. The value is on the IAM and STS quotas page; raising it takes a support ticket, not Service Quotas. Cache credentials until shortly before `Expiration` rather than calling per request.
- **Money.** No charge for this call was found in the collected sources (UNVERIFIED); check AWS pricing before assuming none.

## Endpoint choice

Use a Regional endpoint (`sts.<region>.amazonaws.com`) where you can; AWS recommends it. Since April 2025 the global endpoint `sts.amazonaws.com` is served in the caller's Region for Regions enabled by default, but requests from opt-in Regions still go to US East (N. Virginia). If STS is not active in the Region you call, the error is `RegionDisabled`.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 131 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/aws/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
