If you’ve tried to assume a role across AWS accounts and received an “Access Denied” error, you’re not alone. I’ve spent hours debugging cross-account role assumptions in complex multi-account environments, and the issue almost always comes down to one of five specific misconfiguration points. In this post, I’ll walk through exactly what causes AssumeRole failures and how to fix each one systematically.

The Problem

You’re trying to assume a role in another account:

aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/DeployRole \
  --role-session-name deploy-session

And you get this error:

Error Type Error Message
AccessDenied User: arn:aws:iam::111111111111:user/deployer is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::222222222222:role/DeployRole

The error message tells you exactly what’s failing: your user or role doesn’t have permission to assume the target role. But why?

Why Does This Happen?

  • Trust policy in target account is wrong: The role’s trust relationship (assume role policy) doesn’t include your source principal. You’re trying to assume a role that doesn’t trust your account or user
  • Source principal lacks sts:AssumeRole permission: Your user or role in the source account doesn’t have an IAM policy with sts:AssumeRole on the target role ARN
  • External ID mismatch: The target role requires an external ID for security, but you didn’t provide one or provided the wrong one
  • MFA required but not presented: The trust policy requires MFA authentication, but you didn’t include an MFA device serial number in your assume-role call
  • Role session duration exceeds maximum: You requested a session duration longer than the role allows (default max is 1 hour for roles)

The Fix

Step 1: Verify Your Source Principal

First, confirm who you are in the source account:

aws sts get-caller-identity \
  --query '[Account,Arn,UserId]' \
  --output text

This outputs your account ID and your exact ARN. You’ll need this ARN for the next step.

Step 2: Check the Target Role’s Trust Policy

Get the trust policy (assume role policy document) from the target account:

aws iam get-role \
  --role-name DeployRole \
  --query 'Role.AssumeRolePolicyDocument' \
  --output text

Look for a Principal that matches your source. It should look like:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:user/deployer"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

If your principal ARN is not in the Principal block, that’s your first problem. You can use * for the AWS account to allow anyone in that account:

"Principal": {
  "AWS": "arn:aws:iam::111111111111:root"
}

Step 3: Check Source IAM Policy

In your source account, verify your user or role has permission to assume the target role:

aws iam get-user-policy \
  --user-name deployer \
  --policy-name AssumeRolePolicy \
  --query 'UserPolicy.PolicyDocument' \
  --output text

The policy should include:

{
  "Effect": "Allow",
  "Action": "sts:AssumeRole",
  "Resource": "arn:aws:iam::222222222222:role/DeployRole"
}

If this is missing, add it.

Step 4: Handle External IDs (if configured)

If the target role requires an external ID (common for cross-account access security), you must provide it:

aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/DeployRole \
  --role-session-name deploy-session \
  --external-id MyExternalIdValue123 \
  --duration-seconds 3600

The external ID is a shared secret between accounts. If you don’t know it, ask the target account administrator.

Step 5: Handle MFA (if required)

If the trust policy requires MFA, you must include your MFA device:

aws sts assume-role \
  --role-arn arn:aws:iam::222222222222:role/DeployRole \
  --role-session-name deploy-session \
  --serial-number arn:aws:iam::111111111111:mfa/deployer \
  --token-code 123456 \
  --duration-seconds 3600

The token-code is your current 6-digit MFA code. You can only assume roles with MFA interactively (not in automated deployments unless you use a virtual MFA device).

Diagnostic Checklist

Use this checklist to systematically verify each layer:

  1. Does the target role’s trust policy include your source principal? → Check arn:aws:iam::111111111111:user/deployer or arn:aws:iam::111111111111:root
  2. Does your source IAM policy have sts:AssumeRole on the target role ARN? → Run get-user-policy or get-role-policy
  3. If external ID is required, did you provide it? → Check the trust policy for ExternalId condition and pass --external-id
  4. If MFA is required, did you provide it? → Check for aws:MultiFactorAuthPresent condition and pass --serial-number and --token-code
  5. Is the requested session duration within the role’s maximum? → Default max is 1 hour unless the role is configured differently

Is This Safe?

Yes. Testing assume-role calls is completely safe — if they fail, no credentials are issued. You’re just verifying your permissions. Assume-role failures don’t lock you out of anything.

Key Takeaway

AssumeRole failures almost always come down to a trust policy mismatch or a missing source IAM permission. Always verify both the target role’s trust policy and your source IAM policy. In my experience, the trust policy is the culprit 70% of the time — it’s the first place I check in a cross-account setup.


Have questions or ran into a different IAM issue? Connect with me on LinkedIn or X.