- name
- Authentication and Credentials for Agentic Workflows
- description
- Comprehensive security patterns for managing authentication in GitHub Agentic Workflows including GitHub token types, credential storage, token rotation, least privilege access control, MCP server authentication, and API key management best practices.
- license
- Apache-2.0
- version
- 2.0.0
- last_updated
- 2026-04-02
- tags
- ["authentication","credentials","security","agentic-workflows","github-tokens","api-keys","secrets-management","least-privilege","token-rotation","mcp-authentication"]
# 🔐 Authentication and Credentials for Agentic Workflows
## 🔴 AI FIRST Quality Principle
> **Apply the AI FIRST principle: never accept first-pass quality. Minimum 2 iterations. Read all output, improve every section. No shortcuts.**
## 📋 Overview
This skill provides comprehensive security patterns for managing authentication and credentials in GitHub Agentic Workflows. It covers GitHub token types, secure credential storage, token rotation strategies, least privilege access control, MCP server authentication, and API key management best practices for production-ready autonomous agent systems.
## 🎯 Core Concepts
### Authentication Architecture
```mermaid
graph TB
subgraph "Credential Sources"
A[GitHub Secrets] --> B[Environment Variables]
C[Vault] --> B
D[AWS Secrets Manager] --> B
end
subgraph "Agent Runtime"
B --> E[Credential Manager]
E --> F{Token Type}
F -->|GITHUB_TOKEN| G[GitHub API]
F -->|PAT| H[Extended Permissions]
F -->|GitHub App| I[Installation Token]
F -->|API Keys| J[External Services]
end
subgraph "MCP Servers"
E --> K[MCP Authentication]
K --> L[GitHub MCP]
K --> M[Custom MCP]
K --> N[Third-Party MCP]
end
subgraph "Security Controls"
E --> O[Least Privilege]
E --> P[Token Rotation]
E --> Q[Audit Logging]
end
style E fill:#00d9ff
style O fill:#ff006e
style P fill:#ffbe0b
```
### Security Principles
1. **Least Privilege**: Minimal permissions required for task
2. **Defense in Depth**: Multiple layers of security
3. **Token Rotation**: Regular credential updates
4. **Audit Trail**: Complete authentication logging
5. **Secure Storage**: Encrypted credential management
6. **Time-Limited Access**: Short-lived tokens when possible
## 🔑 GitHub Token Types
### 1. GITHUB_TOKEN (Automatic)
#### Characteristics
```yaml
# Automatic token provided by GitHub Actions
# - Automatically created per workflow run
# - Expires when workflow completes
# - Scoped to the repository
# - Configurable permissions
permissions:
contents: read # Read repository contents
pull-requests: write # Create/update PRs
issues: write # Create/update issues
statuses: read # Read commit statuses
```
#### Usage Pattern
```yaml
# .github/workflows/agent-pr-review.yml
name: Agent PR Review
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: read
pull-requests: write
jobs:
review:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }} # Automatic token
- name: Run Agent Review
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
node scripts/agents/pr-reviewer.js \
--pr-number=${{ github.event.pull_request.number }}
- name: Post Review Comment
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
await github.rest.pulls.createReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.issue.number,
body: 'Agent review completed ✅',
event: 'COMMENT'
});
```
#### Limitations
```yaml
# GITHUB_TOKEN limitations:
# ❌ Cannot trigger other workflow runs
# ❌ Cannot access other repositories
# ❌ Cannot push to protected branches (unless configured)
# ❌ Expires at end of workflow run
# ❌ Limited to repository permissions
# Use PAT for these scenarios:
# ✅ Triggering workflows
# ✅ Cross-repository operations
# ✅ Protected branch pushes
# ✅ Long-running agent processes
```
### 2. Personal Access Token (PAT)
#### Classic PAT Configuration
```yaml
# GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
#
# Recommended Scopes for Agentic Workflows:
# ✅ repo (Full control of private repositories)
# - repo:status (Access commit status)
# - repo_deployment (Access deployment status)
# - public_repo (Access public repositories)
# - repo:invite (Access repository invitations)
# ✅ workflow (Update GitHub Action workflows)
# ✅ write:packages (Upload packages to GitHub Package Registry)
# ✅ read:packages (Download packages from GitHub Package Registry)
# ✅ admin:org (Full control of organizations)
# - read:org (Read organization data)
# ✅ admin:repo_hook (Full control of repository hooks)
# Expiration: 90 days (recommended for security)
```
#### Fine-Grained PAT (Recommended)
```yaml
# GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
#
# Permissions for Agentic Workflows:
#
# Repository permissions:
# - Actions: Read and write
# - Contents: Read and write
# - Issues: Read and write
# - Metadata: Read-only (mandatory)
# - Pull requests: Read and write
# - Workflows: Read and write
#
# Organization permissions (if needed):
# - Members: Read-only
#
# Account permissions:
# - None (unless required)
#
# Repository access:
# - Only select repositories (principle of least privilege)
#
# Expiration: 90 days
```
#### Usage in Workflows
```yaml
# Store PAT as repository secret:
# Repository Settings → Secrets and variables → Actions → New repository secret
# Name: COPILOT_MCP_GITHUB_PERSONAL_ACCESS_TOKEN
jobs:
agent-task:
runs-on: ubuntu-latest
steps:
- name: Checkout with PAT
uses: actions/checkout@v4
with:
token: ${{ secrets.COPILOT_MCP_GITHUB_PERSONAL_ACCESS_TOKEN }}
fetch-depth: 0
- name: Run Agent with PAT
env:
GITHUB_TOKEN: ${{ secrets.COPILOT_MCP_GITHUB_PERSONAL_ACCESS_TOKEN }}
run: |
# Agent can now:
# - Push to protected branches
# - Trigger other workflows
# - Access multiple repositories
node scripts/agents/cross-repo-agent.js
- name: Create PR (Triggers Workflows)
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.COPILOT_MCP_GITHUB_PERSONAL_ACCESS_TOKEN }}
title: 'Agent Update'
body: 'Automated changes by agent'
branch: 'agent/update'
```
### 3. GitHub App Token
#### App Creation and Configuration
```bash
# 1. Create GitHub App
# GitHub Settings → Developer settings → GitHub Apps → New GitHub App
# App Configuration:
# - Name: Agentic Workflow Bot
# - Homepage URL: https://github.com/your-org/your-repo
# - Webhook: Optional (for event-driven agents)
# - Permissions:
# Repository permissions:
# - Actions: Read & write
# - Contents: Read & write
# - Issues: Read & write
# - Pull requests: Read & write
# - Workflows: Read & write
# Organization permissions:
# - Members: Read-only (if needed)
# 2. Generate Private Key
# Download private key (PEM file)
# 3. Install App on Repository
# Install App → Select repositories
# 4. Store App Credentials
# - APP_ID: From app settings
# - PRIVATE_KEY: PEM file content (as secret)
# - INSTALLATION_ID: From installation URL
```
#### Generate Installation Token
```javascript
// scripts/agents/lib/github-app-auth.js
import { createAppAuth } from '@octokit/auth-app';
import { Octokit } from '@octokit/rest';
import fs from 'fs';
/**
* GitHub App authentication for agentic workflows
*/
class GitHubAppAuth {
constructor(options = {}) {
this.appId = options.appId || process.env.GITHUB_APP_ID;
this.privateKey = options.privateKey || process.env.GITHUB_APP_PRIVATE_KEY;
this.installationId = options.installationId || process.env.GITHUB_APP_INSTALLATION_ID;
if (!this.appId || !this.privateKey) {
throw new Error('GitHub App credentials not configured');
}
}
/**
* Create authenticated Octokit instance
*/
async createOctokit() {
const auth = createAppAuth({
appId: this.appId,
privateKey: this.privateKey,
installationId: this.installationId
});
const { token } = await auth({ type: 'installation' });
return new Octokit({
auth: token,
userAgent: 'agentic-workflow-bot/1.0.0'
});
}
/**
* Get installation token (for direct use)
*/
async getInstallationToken() {
const auth = createAppAuth({
appId: this.appId,
privateKey: this.privateKey,
installationId: this.installationId
});
const { token, expiresAt, permissions } = await auth({ type: 'installation' });
return {
token,
expiresAt: new Date(expiresAt),
permissions
};
}
/**
* Revoke installation token (cleanup)
*/
async revokeToken(token) {
const octokit = new Octokit({ auth: token });
await octokit.apps.deleteToken({
client_id: this.appId,
access_token: token
});
}
}
export default GitHubAppAuth;
// Usage in workflow
const appAuth = new GitHubAppAuth({
appId: process.env.GITHUB_APP_ID,
privateKey: process.env.GITHUB_APP_PRIVATE_KEY,
installationId: process.env.GITHUB_APP_INSTALLATION_ID
});
const octokit = await appAuth.createOctokit();
// Use octokit for API calls
const { data: pr } = await octokit.pulls.get({
owner: 'owner',
repo: 'repo',
pull_number: 123
});
```
#### Workflow Integration
```yaml
# .github/workflows/agent-github-app.yml
name: Agent with GitHub App
on:
issues:
types: [opened]
jobs:
process-issue:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Generate App Token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.GITHUB_APP_ID }}
private-key: ${{ secrets.GITHUB_APP_PRIVATE_KEY }}
- name: Run Agent with App Token
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
node scripts/agents/issue-processor.js \
--issue-number=${{ github.event.issue.number }}
- name: Cleanup (token automatically revoked)
run: echo "Token expires in 1 hour"
```
## 🔒 Credential Storage
### 1. GitHub Secrets
#### Repository Secrets
```bash
# Add secret via GitHub UI:
# Repository → Settings → Secrets and variables → Actions → New repository secret
# Or via GitHub CLI:
gh secret set ANTHROPIC_API_KEY --body "sk-ant-..."
gh secret set OPENAI_API_KEY --body "sk-..."
gh secret set MCP_DATABASE_URL --body "postgresql://..."
# List secrets:
gh secret list
# Delete secret:
gh secret delete ANTHROPIC_API_KEY
```
#### Environment Secrets
```yaml
# Use GitHub Environments for stage-specific secrets
# Repository → Settings → Environments → New environment
# Development environment
name: development
secrets:
- API_KEY: dev-key-123
- DATABASE_URL: postgresql://dev-db
# Production environment
name: production
secrets:
- API_KEY: prod-key-456
- DATABASE_URL: postgresql://prod-db
protection_rules:
- required_reviewers: 2
- wait_timer: 5 # minutes
```
```yaml
# Use environment secrets in workflow
jobs:
deploy-dev:
runs-on: ubuntu-latest
environment: development
steps:
- name: Deploy Agent
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: ./deploy.sh
deploy-prod:
runs-on: ubuntu-latest
environment: production
needs: deploy-dev
steps:
- name: Deploy Agent
env:
API_KEY: ${{ secrets.API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
run: ./deploy.sh
```
#### Organization Secrets
```bash
# For multi-repository access
# Organization → Settings → Secrets and variables → Actions
# Add organization secret:
gh secret set SHARED_API_KEY \
--org your-org \
--repos "repo1,repo2,repo3" \
--body "shared-key-789"
```
### 2. External Secret Managers
#### AWS Secrets Manager
```yaml
# .github/workflows/agent-aws-secrets.yml
name: Agent with AWS Secrets
jobs:
agent-task:
runs-on: ubuntu-latest
permissions:
id-token: write # For OIDC authentication
contents: read
steps:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsRole
aws-region: us-east-1
- name: Retrieve Secrets
id: secrets
run: |
# Get secret from AWS Secrets Manager
SECRET_JSON=$(aws secretsmanager get-secret-value \
--secret-id agentic-workflow/production \
--query SecretString \
--output text)
# Parse and export secrets
echo "::add-mask::$(echo $SECRET_JSON | jq -r '.api_key')"
echo "API_KEY=$(echo $SECRET_JSON | jq -r '.api_key')" >> $GITHUB_ENV
- name: Run Agent with Secret
env:
API_KEY: ${{ env.API_KEY }}
run: node scripts/agents/secure-agent.js
```
#### HashiCorp Vault
```yaml
# .github/workflows/agent-vault.yml
在 GitHub 查看