FREE TOOL

AWS IAM Access Denied Decoder

Paste an AWS access denied error: see who was denied which action on which resource, which policy type denied it - explicitly or implicitly - and what to check.

  • Your data never leaves your browser: everything is calculated by JavaScript on this page, not on a server.
  • Nothing you enter is uploaded, processed on a server or stored. Check it in your browser's developer tools (Network tab).
  • Once the page has loaded, the tool works without an internet connection.

Access denied error

The whole message, as the AWS CLI, an SDK, the console or CloudTrail shows it - an encoded authorization message, or its decoded JSON, works too.

Or pick a message

Examples from AWS's documentation, one for each kind of denial.

See result ↓

Identity-based policy statement

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "codecommit:ListRepositories",
      "Resource": "*"
    }
  ]
}

It allows exactly the denied action on the denied resource. A call often needs more actions - the IAM Permissions Finder lists all of them for a CLI command or SDK call.

IAM policy types and how AWS evaluates them are core AWS Security Specialty topicsTry free SCS-C02 practice questions with answers and explanations.SCS-C02 questions →

How to read an AWS access denied message

Most AWS services write access denied errors in one format: User: PRINCIPAL is not authorized to perform: ACTION on resource: RESOURCE because CONTEXT. The principal is the ARN of the user, role or role session that made the request; the action is the IAM action that was checked, which is not always named like the API call; the resource is the ARN the action was checked against. The context says which type of policy denied the request, and how:

  • Explicit deny - with an explicit deny in a TYPE policy, sometimes followed by the policy's ARN. A Deny statement matched the request; no Allow anywhere can override it.
  • Implicit deny - because no TYPE policy allows the ACTION action. Nothing denied the request, but no statement of that policy type allowed it, and every request is denied unless something allows it.

When several policies deny a request, the message names only one policy type and does not say how many policies denied it - after fixing one, the same call can fail on the next. Some services do not use this format at all; the decoder then goes through the policy types in the order worth checking.

Where to fix each policy type

Policy type in the messageWhat it isWho can fix it
identity-basedPolicies attached to the user or role, directly, through a group or inlineWhoever manages the account's IAM; for IAM Identity Center roles, the permission set
resource-basedThe resource's own policy: bucket, key, secret, queue, topic or function policyThe resource's owner
role trustThe trust policy of the role being assumed (sts:AssumeRole)The role's account
permissions boundaryThe maximum permissions set on the user or roleWhoever set the boundary, usually the account's administrators
sessionA policy passed when the temporary credentials were created (AssumeRole's Policy or PolicyArns, GetFederationToken)Whatever creates the session: a CI system, a broker, a script
service controlAn SCP of AWS Organizations on the account, its OUs or the rootThe organization's management account
resource controlAn RCP of AWS Organizations on the resource's accountThe organization's management account
VPC endpointThe policy of the VPC endpoint the request went throughThe endpoint's owner

A role session such as arn:aws:sts::111122223333:assumed-role/app-role/i-0abc123 gets its permissions from the role arn:aws:iam::111122223333:role/app-role: fix the role's policies, and name the role, not the session, in a resource or trust policy. From another account, both the resource's policy and the caller's identity-based policy must allow the request.

Amazon S3's access denied messages

Amazon S3 uses the same format, with the resource in quotes and the policy after , with policy ARN: - but only for requests within the same account or AWS organization. A request from another account outside the organization, to a directory bucket, or denied by a VPC endpoint policy gets a bare Access Denied. Instead of a policy type, S3 can also give a reason: public ACLs or public policies blocked by S3 Block Public Access, or uploads with customer-provided keys (SSE-C) blocked by the bucket. Other frequent causes of a bare Access Denied: an object encrypted with a KMS key the caller cannot use, a Requester Pays bucket, and a missing object when the caller has no s3:ListBucket - S3 then answers 403 instead of 404.

Encoded authorization messages (UnauthorizedOperation)

Amazon EC2 and a few other services return UnauthorizedOperation with the details encoded, because they can contain information the caller should not see. Anyone with the sts:DecodeAuthorizationMessage permission can decode it; paste the message into the decoder to get the command, then paste its output back:

aws sts decode-authorization-message --encoded-message ENCODED-MESSAGE --query DecodedMessage --output text

The decoded message says whether a Deny matched (explicitDeny), which statements matched, the principal, action and resource, and the value of every condition key in the request - such as the instance type or Region - which is what to compare with the conditions of your policies. It does not say which policy the statement is in.

Frequently asked questions

Is the error message sent anywhere?

No. The message is decoded in your browser: nothing you paste is uploaded, processed on a server or stored. The page only counts that the decoder was used, with what kind of message and which diagnosis, never the text.

My policy allows the action - why is it still denied?

An explicit deny somewhere else wins over any Allow: in another identity-based policy, the resource's policy, an SCP or RCP, a permissions boundary or a session policy. For an implicit deny, the Allow may not match this request: another resource ARN (a bucket instead of its objects), a condition on tags, Region or network, or a policy type that has to allow the action too - a permissions boundary, an SCP, or the resource's policy across accounts.

How is this different from the IAM Permissions Finder?

The IAM Permissions Finder starts from a CLI command or SDK call and lists every action it needs, with a least-privilege policy. The decoder starts from the error: it tells which policy type stopped one request and what to check in it, including the policy types no Allow of yours can fix.

Why does the message name an action I did not call?

IAM actions are not API calls: aws lambda invoke is authorized by lambda:InvokeFunction, and one call can need actions of other services, such as iam:PassRole or kms:Decrypt. The message names the action that was denied, not the call.

References

Troubleshoot access denied error messages
Troubleshoot access denied (403 Forbidden) errors in Amazon S3
AWS STS DecodeAuthorizationMessage
Policy evaluation logic
Cross-account policy evaluation logic
IAM identifiers