I originally published this deep-dive on troubleshooting the 'Not authorized to perform sts:AssumeRoleWithWebIdentity' error in EKS over at DevOpsStart. It walks through the three most common root causes — OIDC provider mismatch, trust policy conditions, and audience misalignment — and shows you how to fix each one in minutes.
Introduction
When a pod in Amazon EKS tries to assume an IAM role using a service account annotation and fails with "Not authorized to perform sts:AssumeRoleWithWebIdentity", the root cause is almost always a mismatch between the role's trust policy and the pod's actual web identity token. This error stops your application from accessing any AWS resource. The fix is systematic: validate the OIDC provider, inspect the trust policy, and align the conditions with the token's claims. Following these steps resolves the issue within a few minutes.
Problem
The error message looks like this:
$ aws sts get-caller-identity
An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation: Not authorized to perform sts:AssumeRoleWithWebIdentity
Your pod is annotated with eks.amazonaws.com/role-arn, which triggers the EKS Pod Identity Webhook to inject environment variables (AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE). The AWS SDK in the pod then calls sts:AssumeRoleWithWebIdentity with a JWT token from the filesystem. If the token's claims (issuer, subject, audience) don't match the role's trust policy conditions, AWS rejects the request.
Root Causes
Three main things cause this error:
- OIDC provider mismatch – The IAM OIDC identity provider for your cluster is missing, or its ARN differs from the one in the trust policy. After a cluster upgrade or OIDC provider rotation, the issuer URL can change.
-
Trust policy condition mismatch – The
"Condition"block in the trust policy must specify"sub"assystem:serviceaccount:<namespace>:<service-account-name>and"aud"assts.amazonaws.com. A typo in the namespace or service account name, or a missing condition, causes denial. -
Audience mismatch – The AWS SDK expects the audience claim to be
sts.amazonaws.com. If you set a custom audience in your OIDC provider or in the pod's annotation, the token'saudclaim will differ and the trust policy condition will fail.
Solution
Step 1: Verify the OIDC provider exists
Run these commands to get your cluster's OIDC issuer URL and check the corresponding IAM provider.
$ aws eks describe-cluster --name <your-cluster-name> --query "cluster.identity.oidc.issuer" --output text
https://oidc.eks.us-east-1.amazonaws.com/id/EXAMPLED1234567890ABC
$ aws iam list-open-id-connect-providers --query "OpenIDConnectProviderList[*].Arn"
The ARN should end with the same ID (EXAMPLED1234567890ABC). If the provider is missing, create it (official documentation).
Step 2: Inspect the current trust policy
$ aws iam get-role --role-name <your-role-name> --query "Role.AssumeRolePolicyDocument"
Compare it to the correct template. The "Action" must be "sts:AssumeRoleWithWebIdentity", and the "Condition" block must look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<account-id>:oidc-provider/oidc.eks.<region>.amazonaws.com/id/<id>"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.<region>.amazonaws.com/id/<id>:sub": "system:serviceaccount:<namespace>:<service-account-name>",
"oidc.eks.<region>.amazonaws.com/id/<id>:aud": "sts.amazonaws.com"
}
}
}
]
}
Step 3: Fix the trust policy
If the Principal.Federated ARN or the condition values are wrong, update the policy:
$ aws iam update-assume-role-policy --role-name <your-role-name> --policy-document file://fixed-trust-policy.json
Step 4: Verify inside the pod
Deploy a debug pod that uses the same service account and run:
$ kubectl run debug --image=amazon/aws-cli -n <namespace> --overrides='{"spec":{"serviceAccountName":"<sa-name>"}}' --rm -it -- sh
Inside the pod:
$ cat /var/run/secrets/eks.amazonaws.com/serviceaccount/token | cut -d. -f2 | base64 -d | jq
The output shows the "iss", "sub", and "aud" claims. The aud must be "sts.amazonaws.com" and sub must be "system:serviceaccount:<namespace>:<sa-name>". Then run:
$ aws sts get-caller-identity
If it returns the assumed role ARN, the fix works.
Prevention
To avoid this error in the future:
- Use
eksctl create iamserviceaccountto create both the IAM role and the service account in one command. This automatically generates the correct trust policy. - After a cluster upgrade, verify the OIDC provider ARN hasn't changed. Compare the cluster's issuer URL with the provider ARN.
- For multi-namespace scenarios, use a wildcard in the
subcondition:"stringLike": { "oidc.eks.*:sub": "system:serviceaccount:*:<sa-name>" }.
For a deeper dive into EKS cluster setup, see our tutorial on Deploy an EKS Cluster with Terraform. If you encounter other pod startup issues, check our guide on How to Debug OOMKilled Pods in Kubernetes.
Top comments (0)