Bitbucket Pipelines OIDC to AWS: "Not authorized to perform sts:AssumeRoleWithWebIdentity"
With OpenID Connect, a Pipelines step gets a signed token instead of stored AWS keys, and trades it for a role's temporary credentials. AWS checks the token against an identity provider registered in your account and against the role's trust policy. When something does not match, the AWS CLI stops with one of these:
An error occurred (AccessDenied) when calling the AssumeRoleWithWebIdentity operation: Not authorized to perform sts:AssumeRoleWithWebIdentity An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Incorrect token audience
The step and its variables
Atlassian's article OIDC authentication issues troubleshooting (updated September 25, 2025) puts the step first: it needs oidc: true. The token comes as BITBUCKET_STEP_OIDC_TOKEN, and each step gets its own. Atlassian's newer overview, Integrate Pipelines with resource servers using OIDC, says OIDC is now on by default; the troubleshooting article and the AWS page still set it on the step, and writing it costs nothing.
The AWS CLI then needs the region, the role and a file with the token. From Atlassian's Deploy on AWS using Bitbucket Pipelines OpenID Connect:
image: amazon/aws-cli
pipelines:
default:
- step:
oidc: true
script:
- export AWS_REGION=us-west-2
- export AWS_ROLE_ARN=arn:aws:iam::XXXXXXXXXXXX:role/oidc-demo
- export AWS_WEB_IDENTITY_TOKEN_FILE=$(pwd)/web-identity-token
- echo $BITBUCKET_STEP_OIDC_TOKEN > $(pwd)/web-identity-token
- aws s3 cp s3://bucket/XXXXXX ./XXXXXXX
The troubleshooting article lists the third variable as AWS_WEB_IDENTITY_ROLE_FILE. The AWS CLI does not read that name; its environment variables have AWS_WEB_IDENTITY_TOKEN_FILE, as in the example above.
The identity provider and the audience
In the repository's settings, OpenID Connect under Pipelines shows the Identity provider URL and the Audience. In AWS IAM, Identity providers, Add provider, OpenID Connect takes both. The URL has the form https://api.bitbucket.org/2.0/workspaces/<workspace>/pipelines-config/identity/oidc, and the audience the form ari:cloud:bitbucket::workspace/<workspace UUID>, as in Atlassian's example token. The provider belongs to a workspace, so a repository in another workspace needs its own.
"Incorrect token audience" means the audience in the token is not the one registered in AWS. Atlassian's article on it (Troubleshooting pipeline build failing with ... Incorrect token audience, updated September 25, 2025) says to copy the value from Bitbucket into the provider's audience again. One more way to get there: oidc: audiences: in the YAML, on a step or under options, customizes the audiences in the token (up to 10, Atlassian's overview). The provider in AWS then has to list the value the token carries.
The trust policy and the sub claim
The role's trusted entity is Web identity, with that provider and audience. To narrow it further, the trust policy checks the token's sub, which Atlassian builds as:
{REPOSITORY_UUID}[:{ENVIRONMENT_UUID}]:{STEP_UUID}
- The environment part is there only when the step has a
deploymentenvironment. A policy that requires an environment refuses every step without one. - The UUIDs keep their curly braces, as in Atlassian's example. The OpenID Connect page in Bitbucket shows them under the example payload, with a list to pick the deployment environment.
- The condition key is the provider's address without
https://, followed by:sub.
Atlassian's policy for one repository:
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::{AWS_ACCOUNT_NUMBER}:oidc-provider/api.bitbucket.org/2.0/workspaces/{WORKSPACE}/pipelines-config/identity/oidc"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"api.bitbucket.org/2.0/workspaces/{WORKSPACE}/pipelines-config/identity/oidc:sub": "{REPO_UUID}:{*}"
}
}
}
For deployment steps only, the same page uses "{REPO_UUID}*:{ENVIRONMENT_UUID}:*".
The role works, and the call is still denied
A later call can fail with AccessDeniedException ... because no identity-based policy allows the ... action. Atlassian's article Pipelines gives an error "An error occurred (AccessDeniedException) when calling the operation" despite providing authorization via OIDC (updated September 25, 2025) explains one cause: workspace, repository and deployment variables reach the step as environment variables, and the AWS CLI takes AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY from the environment before it assumes a role with web identity. An old key left in those variables wins. Delete it, or change it on purpose. Otherwise the role itself lacks the permission, and its permissions policy needs the action.
Bitbucket Pipelines in IntelliJ IDEA
Pipeline Inbox for Bitbucket Pipelines, a plugin by Lesstep for JetBrains IDEs 2024.1 or later, lists the pipelines of all your Bitbucket Cloud repositories in an IDE tool window, with their steps, the failed step and the command it stopped at, and the step's log as Bitbucket writes it. The list, steps and logs are free; running, re-running and stopping pipelines are Pro (US$1.50 a month, with a 30-day trial).
Get it on JetBrains Marketplace
Atlassian, Bitbucket and Bitbucket Pipelines are trademarks of Atlassian; AWS is a trademark of Amazon.com, Inc. or its affiliates; IntelliJ IDEA is a trademark of JetBrains s.r.o. This page is not affiliated with or endorsed by Atlassian, Amazon or JetBrains.
More: Test results not showing · A variable is empty · "Host key verification failed" (SSH) · "Cannot connect to the Docker daemon" · "authorization denied by plugin pipelines" (Docker) · "Container 'docker' exceeded memory limit." · Pipelines did not run after a push · "Container 'Build' exceeded memory limit." · "Exceeded build time limit of 120 minutes" · The cache is not used · "unexpected system error" · "command not found" · Submodules not cloned · "We couldn't clone the repository" · "No online runner available" · "No space left on device" · "Step exceeded processing limits" · The artifact is missing in the next step · The build passed before and fails now · Build setup takes too long · "You've run out of build minutes" · "Permission denied to update branch" · "You have reached your pull rate limit" (Docker Hub) · "There is an error in your bitbucket-pipelines.yml" · "This pipeline was paused" (deployments) · "Connection refused" to a service (MySQL, PostgreSQL, Redis) · "Container 'build' failed to pull image" · Bitbucket Pipelines plugins for IntelliJ IDEA, compared · 日本語