[Update] AWS STS now supports provider-specific claim validation for GitHub, Google, CircleCI, and OCI in OIDC federation

[Update] AWS STS now supports provider-specific claim validation for GitHub, Google, CircleCI, and OCI in OIDC federation

2026.02.03

This page has been translated by machine translation. View original

Introduction

Hello everyone, this is Akaike.

Many of you probably use OIDC federation when accessing AWS resources from GitHub Actions.
However, when relying on the sub claim in your trust policy, complex conditions like "allow only this Environment of this branch of this repository" can be quite difficult to implement.

In this context, AWS STS has been updated to support IdP-specific claim validation in OIDC federation.

https://aws.amazon.com/jp/about-aws/whats-new/2026/01/aws-sts-supports-validation-identity-provider-claims/

With this update,
provider-specific claims from GitHub, Google, CircleCI, and Oracle Cloud Infrastructure (OCI) can now be used as condition keys in IAM role trust policies and resource control policies.
This is a particularly welcome update for those who access AWS resources through CI/CD pipelines using GitHub Actions.

In this article, I'll compare the traditional configuration methods with what's now possible after this update, with specific policy examples using GitHub as an example.

Recap of OIDC Federation

First, let's briefly review how OIDC federation works as background knowledge.

General Mechanism of OIDC Federation

OIDC federation is a mechanism that uses tokens (JWTs) issued by external Identity Providers (IdPs) to prove "who you are" to another service.

JWTs contain attribute information called claims, and the receiving party validates these claims to determine whether to allow access.

In the AWS Case

When using OIDC federation with AWS, you use the AWS STS AssumeRoleWithWebIdentity API.
When you pass a JWT issued by an IdP to this API, AWS STS validates the token, checks it against the conditions in the IAM role's trust policy, and issues temporary AWS credentials.

For example, with GitHub Actions, the flow is:

    1. A GitHub Actions workflow executes
    1. GitHub issues an OIDC token (JWT)
    1. The workflow calls AssumeRoleWithWebIdentity with that token
    1. AWS STS validates the token and checks it against the IAM role's trust policy conditions
    1. If the conditions are met, temporary credentials are issued

In step 4 above, JWT claims can be used as condition keys, and with this update, the number of available condition keys has increased significantly.

Traditional Condition Keys

Previously, there were no GitHub-specific condition keys, and
the condition keys available for OIDC federation trust policies were limited to these standard claims:

AWS STS Condition Key IdP JWT Claim Description
aud azp (or aud if not set) Audience of the token
sub sub Subject (principal identifier)
amr amr Authentication Method Reference
oaud aud Original audience
email email Email address

Traditional GitHub Actions Trust Policy Example

To control access from GitHub Actions, we mainly used the sub claim.

trust-policy-before.json
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::XXXXXXXXXXXX:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
          "token.actions.githubusercontent.com:sub": "repo:org-name/repo-name:ref:refs/heads/demo"
        }
      }
    }
  ]
}

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#condition-keys-wif

While this method allows for control like "only from the main branch of a specific repository," the sub claim is a string with information packed in this format:

repo:{owner}/{repo}:ref:refs/heads/{branch}
repo:{owner}/{repo}:environment:{environment_name}
repo:{owner}/{repo}:pull_request

https://docs.github.com/en/actions/concepts/security/openid-connect
https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-aws

As you can see, the value of sub changes format depending on the context.
Additionally, you cannot specify the same condition key multiple times within an IAM policy's Condition block.
Therefore, it was not possible to express compound conditions like "specific branch AND specific Environment" using only sub.

As a result, we often had to rely on wildcard matching with StringLike, like this:

trust-policy-before-wildcard.json
{
    "Condition": {
        "StringLike": {
            "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:*"
        }
    }
}

This made fine-grained control by branch or Environment difficult, risking unintended access from workflows.

New Condition Keys

With this update, provider-specific claims can now be used as individual condition keys.
Here's a list of the added condition keys:

Condition Keys Added for GitHub Actions

Condition Key Description
actor Individual account that triggered the workflow
actor_id Immutable ID of the individual account
job_workflow_ref Reference path of reusable workflow
repository Repository where the workflow is running
repository_id Immutable ID of the repository
workflow Workflow name
ref Git reference (branch/tag)
environment Environment name for the job
enterprise_id Enterprise ID containing the repository

Condition Keys Added for Google

Condition Key Description
organization_number Google Cloud/Workspace organization number

Condition Keys Added for CircleCI

Condition Key Description
project_id UUID of the CircleCI project

Condition Keys Added for OCI

Condition Key Description
rpst_id Resource Principal Session Token ID

Sub is Still Required

For trust policies specifying an OIDC provider as Principal, it appears that evaluation of the sub condition key is still mandatory.

When I tried to create an IAM role without specifying token.actions.githubusercontent.com:sub in the trust policy, I got the following error that prevented creation:
So it seems necessary to evaluate sub using either StringEquals, StringLike, or StringEqualsIgnoreCase.

Trust policy with trusted principal arn:aws:iam::XXXXXXXXXXXX:oidc-provider/token.actions.githubusercontent.com must evaluate, using StringEquals, StringLike or StringEqualsIgnoreCase, token.actions.githubusercontent.com:sub which is not scoped to all.

Therefore, the new condition keys don't replace sub, but rather complement it to enable more fine-grained control.

Note that when a Condition block contains multiple condition operators (like StringEquals and StringLike), they are all evaluated as AND conditions.
This means that in addition to the wildcard match on sub, all other condition keys like repository and environment must also be satisfied, resulting in more fine-grained access control than was previously possible.

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-logic-multiple-context-keys-or-values.html

New GitHub Actions Trust Policy Example

Let's look at a trust policy using the new condition keys:

trust-policy-after.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::XXXXXXXXXXXX:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
                    "token.actions.githubusercontent.com:repository": "my-org/my-repo",
                    "token.actions.githubusercontent.com:ref": "refs/heads/main",
                    "token.actions.githubusercontent.com:environment": "production"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:*"
                }
            }
        }
    ]
}

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html#condition-keys-wif

Information that was previously packed into the sub claim can now be specified as individual condition keys.
This allows for expressing compound conditions like "specific repository" AND "main branch" AND "production Environment".

Example Using Immutable IDs

Using immutable IDs allows for more robust policies that aren't affected by repository or account name changes.
Using repository_id (numeric ID) instead of repository (string) ensures the condition doesn't break if the repository is renamed.
Similarly, actor_id handles changes to GitHub usernames.

trust-policy-after-strict.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::XXXXXXXXXXXX:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
                    "token.actions.githubusercontent.com:repository_id": "123456789",
                    "token.actions.githubusercontent.com:actor_id": "123456789"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:my-org/my-repo:*"
                }
            }
        }
    ]
}

Example Specifying a Particular Workflow

Using job_workflow_ref allows restricting access to only workflows that come through a specific reusable workflow.

This enables setups where AWS access is allowed only through common deployment workflows managed by your organization.
For example, you can prevent deployments that don't go through a workflow managed by the security team, which helps strengthen governance.

trust-policy-reusable-workflow.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::XXXXXXXXXXXX:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
                    "token.actions.githubusercontent.com:job_workflow_ref": "my-org/shared-workflows/.github/workflows/deploy.yml@refs/heads/main"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:my-org/*"
                }
            }
        }
    ]
}

Enterprise-Wide Control Example

For GitHub Enterprise Cloud users, enterprise_id can allow access from all repositories within an Enterprise while blocking external access.
This eliminates the need to list individual repositories and update the trust policy whenever a new repository is added.

trust-policy-enterprise.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::XXXXXXXXXXXX:oidc-provider/token.actions.githubusercontent.com"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
                    "token.actions.githubusercontent.com:enterprise_id": "345"
                },
                "StringLike": {
                    "token.actions.githubusercontent.com:sub": "repo:my-org/*"
                }
            }
        }
    ]
}

Terraform Configuration Examples

Now let's look at practical examples of configuring OIDC providers and IAM roles with Terraform.

Traditional Configuration

before/main.tf
# OIDC Provider
resource "aws_iam_openid_connect_provider" "github_actions" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
}

# IAM Role
resource "aws_iam_role" "github_actions_deploy" {
  name = "github-actions-deploy"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Federated = aws_iam_openid_connect_provider.github_actions.arn
        }
        Action = "sts:AssumeRoleWithWebIdentity"
        Condition = {
          StringEquals = {
            "token.actions.githubusercontent.com:aud" = "sts.amazonaws.com"
            "token.actions.githubusercontent.com:sub" = "repo:my-org/my-repo:ref:refs/heads/main"
          }
        }
      }
    ]
  })
}

Updated Configuration

As mentioned earlier, sub is still required, so we add new condition keys alongside sub.
It's now much clearer at a glance what each condition is restricting.

after/main.tf
# OIDC Provider
resource "aws_iam_openid_connect_provider" "github_actions" {
  url             = "https://token.actions.githubusercontent.com"
  client_id_list  = ["sts.amazonaws.com"]
}

# IAM Role
resource "aws_iam_role" "github_actions_deploy" {
  name = "github-actions-deploy"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Effect = "Allow"
        Principal = {
          Federated = aws_iam_openid_connect_provider.github_actions.arn
        }
        Action = "sts:AssumeRoleWithWebIdentity"
        Condition = {
          StringEquals = {
            "token.actions.githubusercontent.com:aud"         = "sts.amazonaws.com"
            "token.actions.githubusercontent.com:repository"   = "my-org/my-repo"
            "token.actions.githubusercontent.com:ref"          = "refs/heads/main"
            "token.actions.githubusercontent.com:environment"  = "production"
          }
          StringLike = {
            "token.actions.githubusercontent.com:sub" = "repo:my-org/my-repo:*"
          }
        }
      }
    ]
  })
}

Conclusion

I've summarized AWS STS's support for IdP-specific claim validation in OIDC federation.

The ability to use individual condition keys for information previously packed into the sub claim has improved policy readability and maintainability.
This is a welcome update for organizations using GitHub Actions CI/CD pipelines, in terms of both security and operations.
It might be a good opportunity to review your existing OIDC federation settings and transition to more fine-grained conditions.

I hope this helps improve the security of your CI/CD pipelines.

Share this article

FacebookHatena blogX

Related articles