diff options
| author | sillylaird <sillyfanboy@gmail.com> | 2026-09-03 00:33:59 +0000 |
|---|---|---|
| committer | sillylaird <sillyfanboy@gmail.com> | 2026-09-03 00:33:59 +0000 |
| commit | 898b52edcb47bcb3e9d6106e74ca73e74ea01e70 (patch) | |
| tree | 85c6ee5ad58b860144551184d4cf86b560c62b91 /.agents/skills/mcp-integration/references/authentication.md | |
| download | www-main.tar.gz www-main.zip | |
Diffstat (limited to '')
| -rw-r--r-- | .agents/skills/mcp-integration/references/authentication.md | 549 |
1 files changed, 549 insertions, 0 deletions
diff --git a/.agents/skills/mcp-integration/references/authentication.md b/.agents/skills/mcp-integration/references/authentication.md new file mode 100644 index 0000000..1d4ff38 --- /dev/null +++ b/.agents/skills/mcp-integration/references/authentication.md @@ -0,0 +1,549 @@ +# MCP Authentication Patterns + +Complete guide to authentication methods for MCP servers in Claude Code plugins. + +## Overview + +MCP servers support multiple authentication methods depending on the server type and service requirements. Choose the method that best matches your use case and security requirements. + +## OAuth (Automatic) + +### How It Works + +Claude Code automatically handles the complete OAuth 2.0 flow for SSE and HTTP servers: + +1. User attempts to use MCP tool +2. Claude Code detects authentication needed +3. Opens browser for OAuth consent +4. User authorizes in browser +5. Tokens stored securely by Claude Code +6. Automatic token refresh + +### Configuration + +```json +{ + "service": { + "type": "sse", + "url": "https://mcp.example.com/sse" + } +} +``` + +No additional auth configuration needed! Claude Code handles everything. + +### Supported Services + +**Known OAuth-enabled MCP servers:** +- Asana: `https://mcp.asana.com/sse` +- GitHub (when available) +- Google services (when available) +- Custom OAuth servers + +### OAuth Scopes + +OAuth scopes are determined by the MCP server. Users see required scopes during the consent flow. + +**Document required scopes in your README:** +```markdown +## Authentication + +This plugin requires the following Asana permissions: +- Read tasks and projects +- Create and update tasks +- Access workspace data +``` + +### Token Storage + +Tokens are stored securely by Claude Code: +- Not accessible to plugins +- Encrypted at rest +- Automatic refresh +- Cleared on sign-out + +### Troubleshooting OAuth + +**Authentication loop:** +- Clear cached tokens (sign out and sign in) +- Check OAuth redirect URLs +- Verify server OAuth configuration + +**Scope issues:** +- User may need to re-authorize for new scopes +- Check server documentation for required scopes + +**Token expiration:** +- Claude Code auto-refreshes +- If refresh fails, prompts re-authentication + +## Token-Based Authentication + +### Bearer Tokens + +Most common for HTTP and WebSocket servers. + +**Configuration:** +```json +{ + "api": { + "type": "http", + "url": "https://api.example.com/mcp", + "headers": { + "Authorization": "Bearer ${API_TOKEN}" + } + } +} +``` + +**Environment variable:** +```bash +export API_TOKEN="your-secret-token-here" +``` + +### API Keys + +Alternative to Bearer tokens, often in custom headers. + +**Configuration:** +```json +{ + "api": { + "type": "http", + "url": "https://api.example.com/mcp", + "headers": { + "X-API-Key": "${API_KEY}", + "X-API-Secret": "${API_SECRET}" + } + } +} +``` + +### Custom Headers + +Services may use custom authentication headers. + +**Configuration:** +```json +{ + "service": { + "type": "sse", + "url": "https://mcp.example.com/sse", + "headers": { + "X-Auth-Token": "${AUTH_TOKEN}", + "X-User-ID": "${USER_ID}", + "X-Tenant-ID": "${TENANT_ID}" + } + } +} +``` + +### Documenting Token Requirements + +Always document in your README: + +```markdown +## Setup + +### Required Environment Variables + +Set these environment variables before using the plugin: + +\`\`\`bash +export API_TOKEN="your-token-here" +export API_SECRET="your-secret-here" +\`\`\` + +### Obtaining Tokens + +1. Visit https://api.example.com/tokens +2. Create a new API token +3. Copy the token and secret +4. Set environment variables as shown above + +### Token Permissions + +The API token needs the following permissions: +- Read access to resources +- Write access for creating items +- Delete access (optional, for cleanup operations) +\`\`\` +``` + +## Environment Variable Authentication (stdio) + +### Passing Credentials to Server + +For stdio servers, pass credentials via environment variables: + +```json +{ + "database": { + "command": "python", + "args": ["-m", "mcp_server_db"], + "env": { + "DATABASE_URL": "${DATABASE_URL}", + "DB_USER": "${DB_USER}", + "DB_PASSWORD": "${DB_PASSWORD}" + } + } +} +``` + +### User Environment Variables + +```bash +# User sets these in their shell +export DATABASE_URL="postgresql://localhost/mydb" +export DB_USER="myuser" +export DB_PASSWORD="mypassword" +``` + +### Documentation Template + +```markdown +## Database Configuration + +Set these environment variables: + +\`\`\`bash +export DATABASE_URL="postgresql://host:port/database" +export DB_USER="username" +export DB_PASSWORD="password" +\`\`\` + +Or create a `.env` file (add to `.gitignore`): + +\`\`\` +DATABASE_URL=postgresql://localhost:5432/mydb +DB_USER=myuser +DB_PASSWORD=mypassword +\`\`\` + +Load with: \`source .env\` or \`export $(cat .env | xargs)\` +\`\`\` +``` + +## Dynamic Headers + +### Headers Helper Script + +For tokens that change or expire, use a helper script: + +```json +{ + "api": { + "type": "sse", + "url": "https://api.example.com", + "headersHelper": "${CLAUDE_PLUGIN_ROOT}/scripts/get-headers.sh" + } +} +``` + +**Script (get-headers.sh):** +```bash +#!/bin/bash +# Generate dynamic authentication headers + +# Fetch fresh token +TOKEN=$(get-fresh-token-from-somewhere) + +# Output JSON headers +cat <<EOF +{ + "Authorization": "Bearer $TOKEN", + "X-Timestamp": "$(date -Iseconds)" +} +EOF +``` + +### Use Cases for Dynamic Headers + +- Short-lived tokens that need refresh +- Tokens with HMAC signatures +- Time-based authentication +- Dynamic tenant/workspace selection + +## Security Best Practices + +### DO + +✅ **Use environment variables:** +```json +{ + "headers": { + "Authorization": "Bearer ${API_TOKEN}" + } +} +``` + +✅ **Document required variables in README** + +✅ **Use HTTPS/WSS always** + +✅ **Implement token rotation** + +✅ **Store tokens securely (env vars, not files)** + +✅ **Let OAuth handle authentication when available** + +### DON'T + +❌ **Hardcode tokens:** +```json +{ + "headers": { + "Authorization": "Bearer sk-abc123..." // NEVER! + } +} +``` + +❌ **Commit tokens to git** + +❌ **Share tokens in documentation** + +❌ **Use HTTP instead of HTTPS** + +❌ **Store tokens in plugin files** + +❌ **Log tokens or sensitive headers** + +## Multi-Tenancy Patterns + +### Workspace/Tenant Selection + +**Via environment variable:** +```json +{ + "api": { + "type": "http", + "url": "https://api.example.com/mcp", + "headers": { + "Authorization": "Bearer ${API_TOKEN}", + "X-Workspace-ID": "${WORKSPACE_ID}" + } + } +} +``` + +**Via URL:** +```json +{ + "api": { + "type": "http", + "url": "https://${TENANT_ID}.api.example.com/mcp" + } +} +``` + +### Per-User Configuration + +Users set their own workspace: + +```bash +export WORKSPACE_ID="my-workspace-123" +export TENANT_ID="my-company" +``` + +## Authentication Troubleshooting + +### Common Issues + +**401 Unauthorized:** +- Check token is set correctly +- Verify token hasn't expired +- Check token has required permissions +- Ensure header format is correct + +**403 Forbidden:** +- Token valid but lacks permissions +- Check scope/permissions +- Verify workspace/tenant ID +- May need admin approval + +**Token not found:** +```bash +# Check environment variable is set +echo $API_TOKEN + +# If empty, set it +export API_TOKEN="your-token" +``` + +**Token in wrong format:** +```json +// Correct +"Authorization": "Bearer sk-abc123" + +// Wrong +"Authorization": "sk-abc123" +``` + +### Debugging Authentication + +**Enable debug mode:** +```bash +claude --debug +``` + +Look for: +- Authentication header values (sanitized) +- OAuth flow progress +- Token refresh attempts +- Authentication errors + +**Test authentication separately:** +```bash +# Test HTTP endpoint +curl -H "Authorization: Bearer $API_TOKEN" \ + https://api.example.com/mcp/health + +# Should return 200 OK +``` + +## Migration Patterns + +### From Hardcoded to Environment Variables + +**Before:** +```json +{ + "headers": { + "Authorization": "Bearer sk-hardcoded-token" + } +} +``` + +**After:** +```json +{ + "headers": { + "Authorization": "Bearer ${API_TOKEN}" + } +} +``` + +**Migration steps:** +1. Add environment variable to plugin README +2. Update configuration to use ${VAR} +3. Test with variable set +4. Remove hardcoded value +5. Commit changes + +### From Basic Auth to OAuth + +**Before:** +```json +{ + "headers": { + "Authorization": "Basic ${BASE64_CREDENTIALS}" + } +} +``` + +**After:** +```json +{ + "type": "sse", + "url": "https://mcp.example.com/sse" +} +``` + +**Benefits:** +- Better security +- No credential management +- Automatic token refresh +- Scoped permissions + +## Advanced Authentication + +### Mutual TLS (mTLS) + +Some enterprise services require client certificates. + +**Not directly supported in MCP configuration.** + +**Workaround:** Wrap in stdio server that handles mTLS: + +```json +{ + "secure-api": { + "command": "${CLAUDE_PLUGIN_ROOT}/servers/mtls-wrapper", + "args": ["--cert", "${CLIENT_CERT}", "--key", "${CLIENT_KEY}"], + "env": { + "API_URL": "https://secure.example.com" + } + } +} +``` + +### JWT Tokens + +Generate JWT tokens dynamically with headers helper: + +```bash +#!/bin/bash +# generate-jwt.sh + +# Generate JWT (using library or API call) +JWT=$(generate-jwt-token) + +echo "{\"Authorization\": \"Bearer $JWT\"}" +``` + +```json +{ + "headersHelper": "${CLAUDE_PLUGIN_ROOT}/scripts/generate-jwt.sh" +} +``` + +### HMAC Signatures + +For APIs requiring request signing: + +```bash +#!/bin/bash +# generate-hmac.sh + +TIMESTAMP=$(date -Iseconds) +SIGNATURE=$(echo -n "$TIMESTAMP" | openssl dgst -sha256 -hmac "$SECRET_KEY" | cut -d' ' -f2) + +cat <<EOF +{ + "X-Timestamp": "$TIMESTAMP", + "X-Signature": "$SIGNATURE", + "X-API-Key": "$API_KEY" +} +EOF +``` + +## Best Practices Summary + +### For Plugin Developers + +1. **Prefer OAuth** when service supports it +2. **Use environment variables** for tokens +3. **Document all required variables** in README +4. **Provide setup instructions** with examples +5. **Never commit credentials** +6. **Use HTTPS/WSS only** +7. **Test authentication thoroughly** + +### For Plugin Users + +1. **Set environment variables** before using plugin +2. **Keep tokens secure** and private +3. **Rotate tokens regularly** +4. **Use different tokens** for dev/prod +5. **Don't commit .env files** to git +6. **Review OAuth scopes** before authorizing + +## Conclusion + +Choose the authentication method that matches your MCP server's requirements: +- **OAuth** for cloud services (easiest for users) +- **Bearer tokens** for API services +- **Environment variables** for stdio servers +- **Dynamic headers** for complex auth flows + +Always prioritize security and provide clear setup documentation for users. |
