plugins/patterns/skills/token-lifecycle-management/SKILL.md
Token expiration handling, refresh strategies, and caching patterns for long-running workflows. Manage installation token lifecycle and rate limits in GitHub Actions.
npx skillsauth add adaptive-enforcement-lab/claude-skills token-lifecycle-managementInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Installation token lifecycle management enables:
Token Expiration
Installation tokens expire exactly 1 hour after generation. Plan refresh strategies for workflows exceeding 50 minutes to account for clock drift and API latency.
See the full implementation guide in the source documentation.
The actions/create-github-app-token@v2 action automatically refreshes tokens in long-running jobs.
name: Long-Running Workflow with Auto-Refresh
on:
workflow_dispatch:
jobs:
long-operation:
runs-on: ubuntu-latest
steps:
- name: Generate token
id: app_token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CORE_APP_ID }}
private-key: ${{ secrets.CORE_APP_PRIVATE_KEY }}
owner: adaptive-enforcement-lab
- name: Long-running operation (2+ hours)
env:
GH_TOKEN: ${{ steps.app_token.outputs.token }}
run: |
# Action automatically refreshes token in background
for i in {1..150}; do
echo "Iteration $i at $(date)"
# API calls use fresh token automatically
gh api user --jq .login
# Sleep for 1 minute (150 iterations = 2.5 hours)
sleep 60
done
How it works:
GITHUB_TOKEN environment variable with new tokenAuto-Refresh Best Practice
Always use
actions/create-github-app-token@v2for long-running workflows. Manual refresh is only needed for custom token generation implementations.
For workflows with custom token generation or explicit refresh control.
name: Manual Token Refresh
on:
workflow_dispatch:
jobs:
manual-refresh:
runs-on: ubuntu-latest
steps:
- name: Multi-hour operation with manual refresh
env:
APP_ID: ${{ secrets.CORE_APP_ID }}
PRIVATE_KEY: ${{ secrets.CORE_APP_PRIVATE_KEY }}
run: |
# Function to generate token
generate_token() {
TOKEN=$(gh api /app/installations \
--jq '.[0].id' | xargs -I {} \
gh api /app/installations/{}/access_tokens \
-X POST --jq .token)
echo "$TOKEN"
}
# Function to check if token needs refresh
needs_refresh() {
local token_age=$1
local max_age=3300 # 55 minutes in seconds
[ $token_age -gt $max_age ]
}
# Initial token generation
export GH_TOKEN=$(generate_token)
TOKEN_CREATED=$(date +%s)
# Long-running operation
for i in {1..150}; do
# Calculate token age
CURRENT_TIME=$(date +%s)
TOKEN_AGE=$((CURRENT_TIME - TOKEN_CREATED))
# Refresh if needed
if needs_refresh $TOKEN_AGE; then
echo "::notice::Token age: $((TOKEN_AGE / 60)) minutes - refreshing"
export GH_TOKEN=$(generate_token)
TOKEN_CREATED=$(date +%s)
fi
# Perform API operation
gh api repos/adaptive-enforcement-lab/example-repo \
--jq '.full_name + " (iteration " + ($i | tostring) + ")"' \
--arg i "$i"
sleep 60
done
Refresh token between workflow steps.
name: Step-Based Token Refresh
on:
workflow_dispatch:
jobs:
step-refresh:
runs-on: ubuntu-latest
steps:
- name: Generate initial token
id: token_1
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CORE_APP_ID }}
private-key: ${{ secrets.CORE_APP_PRIVATE_KEY }}
owner: adaptive-enforcement-lab
- name: Phase 1 (up to 55 minutes)
env:
GH_TOKEN: ${{ steps.token_1.outputs.token }}
run: |
# First batch of operations
for repo in repo-1 repo-2 repo-3; do
gh api repos/adaptive-enforcement-lab/$repo
# Heavy processing...
sleep 1000 # ~16 minutes per repo
done
- name: Refresh token before phase 2
id: token_2
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CORE_APP_ID }}
private-key: ${{ secrets.CORE_APP_PRIVATE_KEY }}
owner: adaptive-enforcement-lab
- name: Phase 2 (next 55 minutes)
env:
GH_TOKEN: ${{ steps.token_2.outputs.token }}
run: |
# Second batch of operations
for repo in repo-4 repo-5 repo-6; do
gh api repos/adaptive-enforcement-lab/$repo
# Heavy processing...
sleep 1000
done
Step Refresh Pattern
Use step-based refresh when you have natural breaking points in your workflow. This provides explicit control and makes token lifecycle visible in workflow logs.
Share refreshed tokens across matrix jobs using artifacts.
name: Matrix with Token Refresh
on:
workflow_dispatch:
jobs:
generate-token:
runs-on: ubuntu-latest
outputs:
token: ${{ steps.app_token.outputs.token }}
steps:
- name: Generate fresh token
id: app_token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CORE_APP_ID }}
private-key: ${{ secrets.CORE_APP_PRIVATE_KEY }}
owner: adaptive-enforcement-lab
process:
needs: generate-token
runs-on: ubuntu-latest
strategy:
matrix:
repo: [repo-1, repo-2, repo-3, repo-4, repo-5]
steps:
- name: Use shared token
env:
GH_TOKEN: ${{ needs.generate-token.outputs.token }}
run: |
# All matrix jobs use same token
gh api repos/adaptive-enforcement-lab/${{ matrix.repo }}
refresh-token:
needs: process
runs-on: ubuntu-latest
if: always()
outputs:
token: ${{ steps.new_token.outputs.token }}
steps:
- name: Generate refreshed token
id: new_token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CORE_APP_ID }}
private-key: ${{ secrets.CORE_APP_PRIVATE_KEY }}
owner: adaptive-enforcement-lab
continue-processing:
needs: [process, refresh-token]
runs-on: ubuntu-latest
if: always()
strategy:
matrix:
repo: [repo-6, repo-7, repo-8, repo-9, repo-10]
steps:
- name: Use refreshed token
env:
GH_TOKEN: ${{ needs.refresh-token.outputs.token }}
run: |
gh api repos/adaptive-enforcement-lab/${{ matrix.repo }}
See reference.md for additional techniques and detailed examples.
See examples.md for code examples.
See reference.md for complete documentation.
documentation
Workload Identity Federation implementation guide. GKE setup, IAM bindings, ServiceAccount configuration, migration from service account keys, and troubleshooting patterns.
development
Secure GitHub Actions trigger patterns for pull requests, forks, and reusable workflows. Preventing privilege escalation and code injection through trigger misconfiguration.
development
Structured framework for evaluating GitHub Actions security before adoption. Trust tiers, risk assessment checklist, and decision tree for action evaluation.
testing
Securely store GitHub App credentials across different environments. GitHub Actions secrets, external CI, Kubernetes, and automated rotation patterns.