Avoiding long-lived tokens on AWS

By Luis Dalmolin

When using AWS, sometimes things we don’t think about can expose security risks to our account. One common pitfall is the use of long-lived access tokens (AWS Access Key and Secret) generated for IAM users to authenticate with the AWS CLI, continuous integration services like GitHub Actions, or even to integrate with services that deploy directly on your AWS account (e.g., Laravel Vapor).

The Problem with Long-Lived Tokens

When developers and teams first start working with AWS, the default approach is often to create users in IAM (Identity and Access Management). A user is typically assigned an Access Key ID and a Secret Access Key. While straightforward, these credentials are static and long-lived by default.

Why Long-Lived Tokens are a Security Risk

  • Exposure: If credentials are leaked in version control systems, logs, or shared externally, they can be exploited until explicitly revoked. You may have heard stories about leaked AWS keys where the scammers have created many servers to mine crypto in the exposed AWS accounts.

  • Persistence: Without rotation policies, these tokens can remain valid for years, creating a wide attack surface for potential breaches.

  • Compliance issues: Some organizations need to comply with standards like SOC 2, ISO 27001 or HIPAA, which often require minimization of long-lived secrets.

Short-Lived Tokens to the Rescue

IAM Identity Center

To avoid storing AWS credentials on your machine for tasks using the AWS CLI (or similar tools), you can use the IAM Identity Center. It allows you to centrally manage access to multiple AWS accounts (along with AWS Organizations) using federated identities and temporary credentials. Here are its benefits:

  • Temporary credentials: Instead of static keys access keys, Identity Center generates temporary tokens (valid for minutes to hours) for authenticated users.

  • Federated access: Supports integration with existing identity providers (e.g., Google Workspace, Okta, Azure AD), reducing the need for AWS-specific credentials and facilitating the management of users.

  • Improved auditing: Every login session is tracked, providing a clear audit trail on AWS CloudTrail of who accessed what and when.

Here’s a quick example of how you can set up a user on the Identity Center and configure your CLI to authenticate and generate short-lived tokens:

1. Enable Identity Center:

  • If you're using AWS Organizations (recommended):

    • Go to the AWS Organizations console and make sure you're in your management account

    • Choose your preferred region (typically your primary region like us-east-1)

    • Navigate to IAM Identity Center and click "Enable"

  • If you have a standalone account:

    • AWS Organizations will be automatically created when you enable Identity Center

    • You'll be asked to create an organization - this is normal and required

    • Your current account will become the management account

  • Then for either case, choose your identity source:

    • Use AWS built-in identity source (simplest to start with)

    • Or connect to your existing provider (Google Workspace, Okta, Azure AD, etc.)

2. Assign permissions:

In the IAM Identity Center:

  • Map users or groups to specific permission under "Permission sets"

  • Then, under "AWS accounts", select the AWS accounts you want to grant permissions, and assign the permission sets you've created to specific users or groups

3. Configure your SSO Profile on the AWS CLI:

Run the following command to configure an SSO profile (This is a one-time configuration):

$ aws configure sso
SSO session name (Recommended): my-sso (Use a name that makes sense to you)
SSO start URL [None]: (Use the URL provided on Identity Center)
SSO region [None]: us-east-1 (Use the region where the Identity Center was configured)
SSO registration scopes [None]: sso:account:access (Fine to leave with the default)

4. Authenticate your CLI session

It will ask you a few additional questions, and then you should have it configured. After that, you can always run the following command to authenticate your local session:

$ aws sso login --profile kirschbaum-playground

The --profile flag uses the “SSO session name” you’ve configured previously, so it is important to use a name that makes sense here. After opening the browser and authenticating, you should be able to run AWS CLI commands against your account.

$ aws s3 ls --profile kirschbaum-playground

Optionally, you can also define your session should always use a specific profile, so you don’t have to specify on each call:

$ export AWS_PROFILE=kirschbaum-playground
$ aws s3 ls

With this, there are no more long-lived tokens on your machine, and your AWS account security is greatly improved.

OIDC for Continuous Integration (CI) and Continuous Deployment (CD)

For CI/CD pipelines, especially with services like GitHub Actions, using OIDC (OpenID Connect) enables secure, short-lived authentication without hardcoding credentials.

How OIDC Works with AWS

OIDC allows AWS to trust external identity providers, like GitHub. Instead of storing long-lived secrets in GitHub repositories, AWS generates temporary credentials at runtime. Here’s a summary on how Github can be authorized to perform actions under AWS accounts using OIDC:

Setting up AWS OIDC in Github

1. Create an Identity Provider in AWS:

In the AWS dashboard, navigate to the IAM console > Identity providers.

Add a new Identity provider, selecting “OpenID Connect” and adding GitHub as with its OIDC URL (https://token.actions.githubusercontent.com). Under “Audience”, use “sts.amazonaws.com”.

2. Create an IAM Role in AWS

The second step is to create an IAM Role (not user), configure a trust policy and add the necessary permissions to perform the tasks your Github action needs. At Kirschbaum, we create separate roles for different purposes, always following the principle of the least privilege, where we assign only the required permissions to each role, limiting its access and scope.

In the role creation wizard, select “Custom Trust Policy”, and in its contents, you can put the following (make sure to replace the variables).

{
"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"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:{gh-org}/{gh-repo}:*"
}
}
}
]
}

Next, you'll need to assign the appropriate permissions to your IAM Role (e.g. Access to an S3 bucket, to the ECS service, etc).

3. Configure your GitHub Actions workflow

Now that we have the OIDC connection configured and the IAM role created, we can set up our Github action. Add a workflow file (deploy.yml) with the following:

name: Preview Deployment (SST)
on:
push:
branches:
- main
 
permissions:
id-token: write
contents: read
 
jobs:
deploy:
runs-on: ubuntu-latest
 
steps:
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
with:
role-to-assume: {arn:aws:iam::123456789012:role/GitHubOIDC}
aws-region: us-east-1
 
- name: Deploy resources
run: aws s3 cp my-app/ s3://my-bucket/ --recursive

When this action runs, GitHub generates a short-lived OIDC token and exchanges it for AWS credentials, valid only for the duration of the workflow. This workflow is simply copying the files to S3, but you can use this method to perform actions in any AWS service and when using deployment tools like Bref or SST.

This example integrates with Github, but of course you can also integrate with other providers like GitLab or Bitbucket.

Key Benefits of OIDC

  • No static secrets: Credentials are generated dynamically. If GitHub gets hacked one day and someone gets access to all existing repository secrets, you are safe.

  • Granular access control: Using the AWS Role Trust Policy, you can restrict access to specific Github organizations, repositories, and branches.

  • Minimal maintenance: AWS and GitHub handle the token exchange process, reducing operational overhead.

Conclusion

Long-lived tokens in AWS are a significant security risk, but AWS provides robust alternatives with IAM Identity Center and OIDC. By using temporary, short-lived credentials, you can significantly reduce the attack surface and maintain compliance with security standards.

Long-lived tokens in AWS pose a significant security risk, but robust alternatives like IAM Identity Center and OIDC offer secure, auditable temporary credentials. By adopting these methods, you can reduce risks, maintain compliance with security standards, and enhance operational efficiency.

If you need any help securing your AWS account or deploying Laravel apps in AWS, Kirschbaum is an AWS certified company and we would be happy to help.

Luis Dalmolin
Chief Technology Officer
Author Image

Interested in speaking with a developer?

Connect with us.
©2025 Kirschbaum Development Group LLC Privacy Policy Terms of Service