Implementing OIDC Authentication
1. Understanding OIDC
| Aspect | Description | Notes |
|---|---|---|
| OpenID Connect (OIDC) | OAuth 2.0 extension for identity | Enables authentication using ID tokens |
| ID Token | JWT containing user identity info | Used for authentication in GitHub Actions |
| Subject Claim | Unique identifier for the user | Typically sub field in JWT |
| Audience Claim | Target audience for the token | Typically aud field in JWT |
Example: OIDC Token Flow
name: OIDC Authentication Flow
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Request ID Token
id: get_id_token
uses: actions/oidc-client@v1
2. Configuring OIDC Provider
| Provider | Configuration | Notes |
|---|---|---|
| GitHub | Uses GitHub Actions as OIDC provider | Automatically available in workflows |
| AWS | Configure IAM role with OIDC trust policy | Requires AWS account setup |
| Azure | Register app in Azure AD and configure trust | Uses Azure Active Directory |
| GCP | Enable Workload Identity and configure trust | Uses Google Cloud IAM |
Note: OIDC provider must support JWT tokens and have a well-defined issuer URL.
3. Setting ID Token Permissions
| Permission | Value | Description |
|---|---|---|
| id-token | write |
Allows workflow to request ID tokens |
| actions:read | read |
Read access to GitHub Actions |
| contents:read | read |
Read access to repository contents |
permissions:
id-token: write
actions: read
contents: read
4. Requesting ID Token
| Method | Usage | Description |
|---|---|---|
| actions/oidc-client | uses: actions/oidc-client@v1 |
Official GitHub OIDC client action |
| GitHub CLI | gh oidc token |
Command-line access to ID tokens |
Example: Requesting ID Token
- name: Request ID Token
id: token
uses: actions/oidc-client@v1
with:
issuer-url: https://token.actions.githubusercontent.com
5. Configuring Trust Relationship
| Resource | Configuration | Description |
|---|---|---|
| AWS IAM Role | Trust policy with oidc.eks.region.amazonaws.com |
Allows GitHub Actions to assume role |
| Azure Service Principal | App registration with trust to GitHub | Enables authentication via OIDC |
| GCP Workload Identity | Binding between GCP service account and GitHub | Allows GitHub to impersonate GCP service account |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
}
}
}
]
}
6. Using Subject Claim
| Claim | Value | Description |
|---|---|---|
| sub | repo:owner/repo:ref:sha |
Unique identifier for the workflow run |
| iss | https://token.actions.githubusercontent.com |
Issuer URL for GitHub OIDC |
Example: Subject Claim in Token
{
"sub": "repo:octocat/Hello-World:ref:refs/heads/main:sha:abc123",
"iss": "https://token.actions.githubusercontent.com"
}
7. Using Audience Claim
| Audience | Value | Description |
|---|---|---|
| AWS | sts.amazonaws.com |
Target audience for AWS STS token |
| Azure | api://AzureADTokenExchange |
Target audience for Azure token |
| GCP | https://iam.googleapis.com/projects/PROJECT_ID/serviceAccounts/SA_EMAIL |
Target audience for GCP token |
Example: Audience Claim in Token
{
"aud": "sts.amazonaws.com",
"iss": "https://token.actions.githubusercontent.com"
}
8. Accessing AWS with OIDC
| Step | Description | Notes |
|---|---|---|
| 1. Setup IAM Role | Create role with OIDC trust policy | Allow GitHub to assume the role |
| 2. Configure Permissions | Attach policies to the role | Define what AWS resources can be accessed |
| 3. Use in Workflow | Request token and assume role | Use aws-actions/configure-aws-credentials |
Example: AWS Access via OIDC
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
role-session-name: GitHubActionsSession
9. Accessing Azure with OIDC
| Step | Description | Notes |
|---|---|---|
| 1. Register App in Azure AD | Create app registration with OIDC support | Enable "Workforce identity federation" |
| 2. Configure Trust | Set up trust relationship with GitHub | Use GitHub's issuer URL as the identity provider |
| 3. Use in Workflow | Request token and authenticate with Azure | Use azure/login action |
Example: Azure Access via OIDC
- name: Login to Azure
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
10. Accessing GCP with OIDC
| Step | Description | Notes |
|---|---|---|
| 1. Enable Workload Identity | Enable GCP Workload Identity in project | Required for OIDC integration |
| 2. Create Service Account | Create GCP service account with required roles | Assign to workload identity |
| 3. Configure Trust | Bind GCP service account to GitHub | Use GitHub's OIDC issuer URL |
Example: GCP Access via OIDC
- name: Setup GCP Service Account
uses: google-github-actions/setup-gcloud@v1
with:
project_id: my-gcp-project
11. Customizing Token Claims
| Claim | Value | Description |
|---|---|---|
| aud | Custom audience value | Override default audience for specific use cases |
| sub | Custom subject identifier | Override default subject for custom workflows |
| exp | Custom expiration time | Adjust token lifetime for security |
Note: Custom claims can be added via GitHub Actions configuration or by modifying the OIDC provider settings.
12. Validating Token
| Validation Step | Description | Tools |
|---|---|---|
| Signature Check | Verify JWT signature using public keys | OpenSSL, JWT libraries |
| Issuer Validation | Ensure issuer matches expected URL | JWT libraries, custom validation logic |
| Audience Validation | Validate that audience matches expected value | JWT libraries, custom validation logic |
Example: Token Validation in Node.js
const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');
const client = jwksClient({
jwksUri: 'https://token.actions.githubusercontent.com/.well-known/jwks'
});
const verify = async (token) => {
const decoded = jwt.decode(token, { complete: true });
const key = await client.getSigningKey(decoded.header.kid);
const verified = jwt.verify(token, key.getPublicKey());
return verified;
};
13. Troubleshooting OIDC
Common Issues and Solutions
- Token Not Found: Ensure
id-token: writepermission is set - Invalid Token: Check that issuer URL matches GitHub's OIDC endpoint
- Permission Denied: Verify that the IAM role or service account has correct permissions
- Token Expiry: Adjust token lifetime or refresh tokens as needed