The traditional method of deploying applications to cloud infrastructure has long relied on static secrets. Developers would generate long-lived access keys, store them as environment variables or secrets within their version control systems, and hope for the best. This approach, while functional, creates a significant security liability. If a secret is leaked, it must be rotated across every service that uses it, a process that is often slow and error-prone. The emergence of federated credentials in GitHub Actions represents a paradigm shift in how continuous integration and continuous deployment (CI/CD) pipelines authenticate with cloud providers. By leveraging OpenID Connect (OIDC), organizations can eliminate the need for long-lived secrets entirely. Instead of storing static credentials, the CI/CD runner requests a short-lived, signed JSON Web Token (JWT) from GitHub, which is then exchanged for access to cloud resources. This mechanism aligns with the principle of least privilege and ensures that access is granted only when a specific workflow is executing, significantly reducing the attack surface of modern software delivery pipelines.
The Architecture of Federated Identity
Federated credentials operate on the principle of trust delegation between an identity provider and a resource provider. In the context of GitHub Actions, GitHub acts as the OpenID Connect (OIDC) identity provider, while cloud platforms like Microsoft Azure or Amazon Web Services (AWS) act as the resource providers. The core advantage of this architecture is that it allows organizations to deploy applications without configuring long-lived secrets within GitHub. Instead, the authentication flow is dynamic and context-aware.
The process begins with the configuration of an application registration or identity provider within the cloud environment. This registration is assigned specific permissions to access the target resources. When a GitHub Actions workflow runs, the runner obtains an access token from the GitHub federated identity provider. This token is not a static secret but a dynamically generated credential that contains claims about the context of the workflow, such as the repository name, the branch being built, and the event that triggered the workflow. This token is then used as a client assertion in the client credentials flow to authenticate with the cloud provider's identity service.
This mechanism is comparable to using a certificate to authenticate to an identity provider like Microsoft Entra ID. However, instead of managing certificates and creating signed JWTs manually, the identity provider is configured to trust the federation token issued by GitHub. This token serves as proof of identity, allowing the workflow to assume the necessary roles or permissions without ever exposing a static secret. The security benefits are substantial: credentials are short-lived, scoped to specific workflows, and cannot be reused outside the context of the GitHub Actions runner.
Implementing Federated Credentials in Azure
Microsoft Azure utilizes Microsoft Entra ID (formerly Azure Active Directory) as its identity backbone. To leverage federated credentials with Azure, organizations must configure a service principal with federated identity providers. The setup process involves creating an application registration in Entra ID and defining the trust relationship with GitHub Actions. This trust relationship is established by specifying the issuer URL of GitHub Actions, which is https://token.actions.githubusercontent.com, and defining the subject claim that matches the specific GitHub entity, such as a branch, pull request, tag, or environment.
The subject claim is critical because it determines the scope of the trust. For example, a federated credential can be configured to trust only the main branch of a specific repository, or only pull requests coming from that repository. This granularity allows organizations to implement strict security policies where only approved code paths can access sensitive resources. The Azure CLI provides commands to create these federated credentials, allowing administrators to define the name, issuer, subject, and audiences for the trust relationship. The audience is typically set to api://AzureADTokenExchange to ensure compatibility with Azure's authentication protocols.
Once the federated credential is configured, the associated service principal must be assigned the appropriate role-based access control (RBAC) permissions. The service principal itself does not have permissions by default; it must be explicitly granted roles such as "Contributor" or "Reader" on the target Azure resources. If the service principal lacks the necessary permissions, the workflow will fail to authenticate or will lack the authority to perform the desired actions. This separation of identity and permission management ensures that access is tightly controlled and auditable.
```powershell
Create federated GitHub credentials for a specific branch
$githubBranchConfig = [PSCustomObject]@{
name = "Federated credential linked to GitHub [$githubBranch] branch @: [$githubOrgName/$githubRepoName]"
issuer = "https://token.actions.githubusercontent.com"
subject = "repo:" + "$githubOrgName/$githubRepoName" + ":ref:refs/heads/" + "$githubBranch"
description = "Federated credential linked to GitHub [$githubBranch] branch @: [$githubOrgName/$githubRepoName]"
audiences = @("api://AzureADTokenExchange")
}
$githubBranchConfigJson = $githubBranchConfig | ConvertTo-Json
$githubBranchConfigJson | az ad app federated-credential create --id $appId --parameters "@-"
Create federated GitHub credentials for Pull Requests
$githubPRConfig = [PSCustomObject]@{
name = "GH-[$githubOrgName-$githubRepoName]-PR"
issuer = "https://token.actions.githubusercontent.com"
subject = "repo:" + "$githubOrgName/$githubRepoName" + ":pull_request"
description = "Federated credential linked to GitHub Pull Requests @: [$githubOrgName/$githubRepoName]"
audiences = @("api://AzureADTokenExchange")
}
$githubPRConfigJson = $githubPRConfig | ConvertTo-Json
$githubPRConfigJson | az ad app federated-credential create --id $appId --parameters "@-"
```
For developers using the Azure SDK in their applications, the DefaultAzureCredential chain in the Azure.Identity library can be extended to support GitHub Actions tokens. While the standard DefaultAzureCredential may not automatically pick up the GitHub Actions OIDC token in all scenarios, custom credentials such as GithubActionsTokenCredential can be implemented to fetch the token from the GitHub Actions environment variables. This allows applications deployed via GitHub Actions to authenticate seamlessly with Azure services like the Graph API without requiring static credentials.
```csharp
using Azure.Core;
using System.Net.Http.Headers;
using System.Net.Http.Json;
namespace Azure.Identity.Federation;
public class GithubActionsTokenCredential : TokenCredential
{
private const string ActionsRequestTokenKey = "ACTIONSIDTOKENREQUESTTOKEN";
private const string ActionsRequestUrlKey = "ACTIONSIDTOKENREQUESTURL";
// Implementation details for fetching the token from GitHub Actions environment variables
}
// Usage in application code
// Replace this line
var credentials = new DefaultAzureCredential();
// with this line
var credentials = new GithubActionsTokenCredential();
// or with this line if you still want to support other credentials
var credentials = new ChainedTokenCredential(new GithubActionsTokenCredential(), new DefaultAzureCredential());
// And then use those credentials to get a token for the Graph API (or any other resource)
var tokenResult = await credentials.GetTokenAsync(new Azure.Core.TokenRequestContext(new[] { "https://graph.microsoft.com/.default" }));
Console.WriteLine(tokenResult.Token);
```
Implementing Federated Credentials in AWS
Amazon Web Services also supports OIDC integration with GitHub Actions, allowing workflows to assume IAM roles without long-term access keys. The setup process involves creating an IAM Identity Provider in the AWS account for GitHub OIDC, using the URL token.actions.githubusercontent.com. This provider establishes the trust relationship between GitHub and AWS IAM.
Next, an IAM role must be created with a trust policy that allows GitHub Actions to assume the role. The trust policy includes conditions that restrict access based on the OIDC claims provided by GitHub. The most critical claims are aud (audience) and sub (subject). The aud claim is typically set to sts.amazonaws.com, and the sub claim specifies the repository, branch, or other entity that is allowed to assume the role. This allows for fine-grained control over which workflows can access which resources.
json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>: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:<GITHUB_ORG>/<GITHUB_REPOSITORY>:ref:refs/heads/<GITHUB_BRANCH>"
}
}
}
]
}
Once the IAM role is created and the trust policy is configured, permissions must be attached to the role to allow access to the necessary AWS resources. In the GitHub Actions workflow, the aws-actions/configure-aws-credentials action is used to assume the role. This action loads the OIDC token from the GitHub-provided environment variables and uses it to call the AWS STS service to assume the role. The workflow must also be granted the id-token: write permission to request the OIDC token.
```yaml
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
jobs:
runjobwith_aws:
runs-on: ubuntu-latest
steps:
- name: Configure AWS Credentials
uses: aws-actions/[email protected]
with:
role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
aws-region: us-east-2
role-session-name: MySessionName
- name: Additional steps
run: |
# Your commands that require AWS credentials
aws sts get-caller-identity
```
The aws-actions/configure-aws-credentials action simplifies the process by handling the token exchange automatically. Developers can also use the actions-oidc-debugger action to inspect the OIDC claims if they are unsure about the subject key or other claim values. This debugging capability is essential for troubleshooting trust policies and ensuring that the conditions are correctly configured.
Workflow Permissions and Token Exchange
For federated credentials to function correctly, the GitHub Actions workflow must be granted the necessary permissions. By default, GitHub Actions workflows run with a restricted set of permissions to enhance security. To request an OIDC token, the workflow must explicitly request the id-token: write permission. This permission allows the workflow runner to request a JWT from the GitHub OIDC provider. Additionally, the contents: read permission is often required for actions like actions/checkout to access the repository code.
yaml
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
The token exchange process involves multiple steps. First, the GitHub Actions runner uses the ACTIONS_ID_TOKEN_REQUEST_TOKEN to request a JWT from the ACTIONS_ID_TOKEN_REQUEST_URL. This JWT contains claims about the workflow context. The runner then uses this JWT to authenticate with the cloud provider's identity service. In Azure, this JWT is used as a client assertion in the client credentials flow. In AWS, it is used in the AssumeRoleWithWebIdentity call. This multi-step process ensures that the token is only used for its intended purpose and is not exposed to unauthorized parties.
The audience claim in the JWT is important for both Azure and AWS. In Azure, the audience is typically api://AzureADTokenExchange. In AWS, the audience is sts.amazonaws.com. These audiences must match the values specified in the cloud provider's configuration for the federated credential to be accepted. If the audience does not match, the authentication will fail. This mechanism adds an additional layer of security by ensuring that the token is only used with the intended resource provider.
Security Considerations and Best Practices
The shift to federated credentials significantly enhances the security posture of CI/CD pipelines. By eliminating long-lived secrets, organizations reduce the risk of credential leakage. If a workflow is compromised, the attacker only gains access to a short-lived token that is valid only for the duration of the workflow execution. This limits the potential damage from a security breach.
However, implementing federated credentials requires careful configuration to avoid unintended access. The subject claim must be configured with the appropriate level of specificity. For example, trusting all branches of a repository may be too permissive for sensitive production resources. Instead, organizations should trust only specific branches, such as main or `master, or specific pull request events. This ensures that only approved code can access production resources.
Additionally, the permissions assigned to the service principal or IAM role must follow the principle of least privilege. Granting excessive permissions increases the risk of accidental data exposure or unauthorized resource modification. Regular audits of role assignments and federated credential configurations are essential to maintain a secure environment.
GitHub Actions also provides tools for debugging and verifying OIDC claims. The actions-oidc-debugger action can be used to inspect the claims in the OIDC token, helping administrators ensure that the trust policies are correctly configured. This visibility is crucial for troubleshooting authentication issues and ensuring that the federated identity setup is working as intended.
Conclusion
Federated credentials in GitHub Actions represent a significant advancement in cloud security and DevOps practices. By leveraging OpenID Connect, organizations can eliminate the need for long-lived secrets and implement fine-grained access controls based on workflow context. This approach enhances security, reduces operational overhead, and aligns with modern cloud security best practices. As more cloud providers adopt OIDC support, federated credentials will become the standard for securing CI/CD pipelines. Organizations that adopt this technology early will benefit from improved security posture and streamlined deployment processes. The transition requires careful planning and configuration, but the long-term benefits outweigh the initial effort. As the ecosystem matures, tools and libraries will continue to evolve, making it easier for developers to integrate federated identity into their workflows. The future of cloud authentication is federated, short-lived, and context-aware, and GitHub Actions is leading the way.