Introduction

AWS deployment credentials in GitHub Actions often come from short-lived STS sessions. That is good security practice, but it creates a failure mode where a long-running S3 deployment starts successfully and then dies halfway through with an expired token. The fix is usually not to go back to long-lived access keys. It is to make session duration, deployment size, and authentication strategy line up.

Symptoms

  • S3 sync or upload steps fail with ExpiredToken
  • A deployment runs for a long time and then dies partway through
  • Small deployments succeed while larger ones fail consistently
  • Static access keys were rotated or temporary role sessions expired during execution

Common Causes

  • The workflow uses temporary credentials with a session shorter than the deployment time
  • Large aws s3 sync operations keep running after the role session expires
  • The workflow uses brittle static secrets instead of OIDC-based role assumption
  • Build and deploy are combined into one long job instead of separate credential scopes

Step-by-Step Fix

  1. 1.Prefer OIDC-based AWS authentication
  2. 2.Let the workflow assume the role with fresh short-lived credentials instead of relying on manually rotated static keys.
yaml
permissions:
  id-token: write
  contents: read
  1. 1.Set a realistic role session duration
  2. 2.If the deploy genuinely takes a long time, configure a session duration that fits the workload and the role’s max session settings.
yaml
- uses: aws-actions/configure-aws-credentials@v4
  with:
    role-to-assume: arn:aws:iam::123456789012:role/github-actions-s3-deploy
    role-duration-seconds: 14400
    aws-region: us-east-1
  1. 1.Break long deployments into smaller steps
  2. 2.Separate build, artifact packaging, and S3 sync work so credentials do not need to survive the whole pipeline lifetime unnecessarily.
  3. 3.Watch deployment duration against token lifetime
  4. 4.If sync time grows over months as assets increase, a previously safe session length may quietly become unsafe.

Prevention

  • Use OIDC and role assumption instead of long-lived AWS keys in GitHub Actions
  • Align role session duration with real deployment time
  • Split long build and deploy chains into separate jobs when possible
  • Monitor deployment duration trends before they outgrow token lifetime