Implementing OIDC Authentication: From GitHub Actions to AWS - A Practical Guide
Table of contents
- What You'll Learn
- Cloud Authentication's Leap Forward: The OIDC Advantage
- Understanding OIDC: Beyond OAuth 2.0
- Core Components of OIDC
- OIDC Authentication Flow Steps
- Overview
- Flow Sequence
- OIDC Authentication Flow in Practice - GitHub Actions & AWS
- Implementing OIDC with GitHub Actions and AWS
- Security Best Practices
- Extras
- Resources and Next Steps
- Conclusion
What You'll Learn
The fundamentals of OIDC authentication
How OIDC differs from OAuth 2.0
Setting up OIDC with GitHub Actions and AWS
Security best practices and troubleshooting
Cloud Authentication's Leap Forward: The OIDC Advantage
Deploying to AWS meant managing long-term access keys in your CI/CD pipeline. Those days introduced constant security concerns: key rotation, secure storage, and the ever-present risk of credential leaks.
Enter OpenID Connect (OIDC) - a game-changing authentication protocol that's transforming how we handle cloud access. By eliminating the need for stored credentials and introducing short-lived tokens, OIDC is setting new standards for secure cloud authentication.
Understanding OIDC: Beyond OAuth 2.0
OIDC builds upon OAuth 2.0's foundation, but with a major difference:
While OAuth 2.0 determines what you can access, OIDC adds the vital component of who you are.
This distinction matters because modern cloud deployments need both authentication (identity verification) and authorization (access control).
Key Advantages of OIDC
Enhanced Security
No stored credentials
Automatic token expiration
Cryptographically signed tokens (JWT)
Improved User Experience
Single Sign-On capabilities
Streamlined authentication flows
Operational Benefits
Centralized identity management
Reduced operational overhead
Core Components of OIDC
Identity Provider (IdP)
Think of the IdP as the trusted security guard of your system. Common examples include:
GitHub
Auth0
Google
Microsoft Azure AD
ID Token Structure
The ID Token is a JWT (JSON Web Token) containing vital information:
{
"iss": "https://token.actions.githubusercontent.com",
"sub": "repo:organization/repository:ref:refs/heads/main",
"aud": "https://github.com/organization",
"exp": 1584979794,
"iat": 1584979494
}
Claims Explained
iss
(Issuer): The token creatorsub
(Subject): The token's intended useraud
(Audience): The token's intended recipientexp
(Expiration): Token expiry timestampiat
(Issued At): Token creation time
Relying Party (RP)
The application seeking to authenticate users. It:
Validates tokens (ID Tokens)
Processes claims
Manages user sessions
Integrates with protected resources
Claims
Identity information embedded into the ID Token, including:
aud (audience): Intended recipient of the token
iss (issuer): Entity that issued the token
exp (expiration): Token expiration timestamp
sub (subject): Subject identifier
Additional custom claims as needed
Issuer
The identifier of the OpenID Provider. This is usually a URL included in tokens to verify their origin.
Access Token
Credentials issued alongside ID Token to the Relying Party, used to:
Access protected resources
Make authenticated API calls
Represent granted permissions
Authorization Code
A temporary code obtained during the authorization process. The Relying Party exchanges this code for an ID Token and an Access Token.
OIDC Authentication Flow Steps
Overview
The OIDC authentication flow involves interactions between three parties:
User
Application (Relying Party)
Identity Provider (IdP)
Each step in the flow serves a specific purpose in establishing secure authentication.
Flow Sequence
1. Initial Access Request
User → Application (Relying Party)
User attempts to access protected resource
Example: Clicking "Login with GitHub" button
Application checks for valid session
2. Authorization Request
Application → Identity Provider
GET /authorize
Host: identity-provider.com
Parameters:
response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=https://url.com/callback
&scope=openid profile email
&nonce=another_random_string
Required Parameters:
Parameter | Description |
response_type | Must be 'code' for authorization code flow |
client_id | Your application's identifier |
redirect_uri | URL where IdP will send the response |
scope | Requested permissions (must include 'openid') |
nonce | Random string to prevent replay attacks |
3. Authentication Prompt
Identity Provider → User
Displays login interface
Handles SSO if applicable
Manages 2FA if configured
Shows consent screen for requested permissions
4. Credential Submission
User → Identity Provider
User provides authentication credentials
Could be username/password
May include 2FA verification
User grants consent for requested scopes
5. Authorization Code Response
Identity Provider → Application
HTTP/1.1 302 Found
Location: https://url.com/callback?
code=AUTHORIZATION_CODE
&state=random_secure_string
6. Token Exchange
Application → Identity Provider
POST /token HTTP/1.1
Host: identity-provider.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=AUTHORIZATION_CODE
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&redirect_uri=https://url.com/callback
7. Token Response
Identity Provider → Application
{
"id_token": "eyJ0eXAi...",
"access_token": "eij_16C7e42F292c6912E7710...",
"token_type": "Bearer",
"expires_in": 3600
}
OIDC Authentication Flow in Practice - GitHub Actions & AWS
In our deployment scenario, let's map the OIDC components to actual services:
Identity Provider (IdP): GitHub - provides identity verification
Relying Party (RP): AWS - consumes and trusts GitHub's identity verification
User: Your GitHub Actions workflow - the entity requesting access
Flow Breakdown with GitHub Actions and AWS
Initial Request
Your GitHub Actions workflow (User) needs to deploy to AWS
AWS (RP) requires authentication
Instead of static credentials, we use OIDC
Authorization Request
GitHub Actions workflow requests authentication from GitHub (IdP)
The request includes the workflow's identity information like:
{ "repository": "org/repo", "workflow": "deploy.yml", "ref": "refs/heads/main" }
Token Generation
GitHub (IdP) generates a JWT token containing claims like:
{ "iss": "https://token.actions.githubusercontent.com", "sub": "repo:myorg/myrepo:ref:refs/heads/main", "aud": "sts.amazonaws.com", "exp": 1584979794 }
Token Verification
AWS (RP) receives the token
Validates it came from GitHub (IdP)
Checks the claims match the trust policy:
{ "Condition": { "StringLike": { "token.actions.githubusercontent.com:sub": "repo:myorg/myrepo:*" } } }
Access Granted
AWS provides temporary credentials
GitHub Actions workflow can now access AWS resources
Credentials automatically expire after the workflow completes
Implementing OIDC with GitHub Actions and AWS
Now, let's look at a practical implementation using GitHub Actions and AWS.
Setting Up AWS OIDC Provider
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list "sts.amazonaws.com" \
--thumbprint-list "6938fd4d98bab03faadb97b34396831e3780aea1"
Creating the IAM Role
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT-ID:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:organization/repository:*"
},
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
}
}
}
]
}
Configuring GitHub Actions
name: Application Deployment
on:
push:
branches: [main]
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
role-to-assume: arn:aws:iam::ACCOUNT-ID:role/ROLE-NAME
aws-region: eu-central-1
- name: Deploy some workload to aws
run: |
aws ...
Security Best Practices
1. Access Control
Apply least privilege principle
Use conditional access
Implement role-based access
Regular access reviews
Extras
Conditional Access
Control access based on:
Repository name
Branch name
Environment
Actor (user/service)
Example condition:
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:sub": [
"repo:org/repo:ref:refs/heads/main",
"repo:org/repo:environment:production"
]
}
}
Resources and Next Steps
Official Documentation
Tools and Libraries
Conclusion
OIDC integration between GitHub Actions and AWS eliminates the need to store AWS credentials as GitHub secrets. Instead, it establishes a trust relationship that generates short-lived tokens during workflow execution, significantly reducing the attack surface of your CI/CD pipeline
Subscribe to my newsletter
Read articles from Oluwatunmise Olatunbosun directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Oluwatunmise Olatunbosun
Oluwatunmise Olatunbosun
Results-driven Software Engineer specializing in cloud-native architectures and scalable systems. Experienced in building resilient systems, automating cloud infrastructure, and implementing reliability patterns that drive measurable business impact.