Lý thuyết
40 phút
Bài 10/15

Credentials Management

Quản lý và bảo mật API keys, OAuth tokens, database credentials trong n8n production

🔑 Credentials Management

Key Security

Credentials là lifeblood của automation - API keys, OAuth tokens, database passwords. Bài này covers best practices để manage và protect chúng.

Credentials in n8n

How n8n Stores Credentials:

Text
1CREDENTIAL STORAGE FLOW
2───────────────────────
3
4User Input Encryption Database
5────────── ────────── ────────
6API Key → AES-256-GCM → Encrypted blob
7Password → + N8N_KEY → in credentials_entity
8Token → →
9
10Only decrypted when workflow runs!

Credential Types:

Text
1COMMON CREDENTIAL TYPES
2───────────────────────
3
4API KEYS:
5├── OpenAI API Key
6├── Stripe API Key
7├── SendGrid API Key
8└── Generic Header Auth
9
10OAUTH:
11├── Google OAuth2
12├── Microsoft OAuth2
13├── Slack OAuth2
14└── Salesforce OAuth2
15
16DATABASE:
17├── PostgreSQL
18├── MySQL
19├── MongoDB
20└── Redis
21
22BASIC AUTH:
23├── HTTP Basic Auth
24├── Custom Header
25└── Query Parameter Auth

Creating Credentials Securely

Best Practices:

Text
1✅ DO:
2• Create credentials with minimal permissions
3• Use service accounts, not personal
4• Set expiration dates where possible
5• Name credentials descriptively
6• Document what each credential is for
7
8❌ DON'T:
9• Reuse credentials across environments
10• Use admin/root credentials
11• Share credentials via chat/email
12• Store unencrypted anywhere
13• Give more permissions than needed

Naming Convention:

Text
1CREDENTIAL NAMING
2─────────────────
3
4Pattern: [Service]-[Environment]-[Purpose]
5
6Examples:
7• OpenAI-Prod-ChatGPT
8• Stripe-Staging-Payments
9• Slack-Prod-Notifications
10• PostgreSQL-Prod-ReadOnly
11• Google-Prod-SheetsSync

API Key Management

Creating Scoped API Keys:

OpenAI:

Text
11. Go to platform.openai.com
22. Create new API key
33. Name: "n8n-production"
44. Set spending limits
55. Copy immediately (shown once!)

Stripe:

Text
11. Dashboard > Developers > API keys
22. Create restricted key
33. Permissions:
4 - Charges: Write
5 - Customers: Read
64. Name: "n8n-automation"

SendGrid:

Text
11. Settings > API Keys
22. Create API Key
33. Permissions: Restricted Access
4 - Mail Send: Full Access
54. Name: "n8n-transactional"

API Key Rotation:

Bash
1#!/bin/bash
2# rotate-api-key.sh
3
4SERVICE=$1
5OLD_KEY=$2
6NEW_KEY=$3
7
8echo "Rotating $SERVICE API key..."
9
10# 1. Create new key in service dashboard
11# 2. Update n8n credential
12docker exec -it n8n sh -c "
13 n8n credential:get --type=${SERVICE}
14 # Update credential via API or manually
15"
16
17# 3. Test with new key
18curl -H "Authorization: Bearer $NEW_KEY" https://api.example.com/test
19
20# 4. Delete old key in service dashboard
21
22echo "Rotation complete. Verify workflows!"

OAuth Credentials

Setting Up OAuth:

Google OAuth2:

Text
11. Google Cloud Console
22. Create OAuth 2.0 Client ID
33. Type: Web Application
44. Redirect URI: https://n8n.yourdomain.com/rest/oauth2-credential/callback
55. Save Client ID and Secret

Microsoft OAuth2:

Text
11. Azure Portal > App registrations
22. New registration
33. Redirect URI: https://n8n.yourdomain.com/rest/oauth2-credential/callback
44. Certificates & secrets > New client secret
55. API permissions > Add required permissions

OAuth Security:

Text
1OAUTH BEST PRACTICES
2────────────────────
3
4✅ Use minimal scopes
5 Google: Only gmail.readonly if only reading
6
7✅ Review app permissions regularly
8 Check for unused scopes
9
10✅ Use organization accounts
11 Not personal Gmail/Microsoft
12
13✅ Set token expiration
14 Refresh tokens when needed
15
16✅ Monitor OAuth app activity
17 Check for unauthorized access

Database Credentials

Creating Database Users:

SQL
1-- PostgreSQL: Create limited user for n8n
2CREATE USER n8n_workflow WITH PASSWORD 'secure_password';
3
4-- Grant only necessary permissions
5GRANT CONNECT ON DATABASE production_db TO n8n_workflow;
6GRANT USAGE ON SCHEMA public TO n8n_workflow;
7GRANT SELECT ON ALL TABLES IN SCHEMA public TO n8n_workflow;
8GRANT INSERT, UPDATE ON specific_table TO n8n_workflow;
9
10-- Read-only user for reporting
11CREATE USER n8n_readonly WITH PASSWORD 'another_password';
12GRANT CONNECT ON DATABASE production_db TO n8n_readonly;
13GRANT SELECT ON ALL TABLES IN SCHEMA public TO n8n_readonly;
SQL
1-- MySQL: Create limited user
2CREATE USER 'n8n_workflow'@'%' IDENTIFIED BY 'secure_password';
3GRANT SELECT, INSERT, UPDATE ON production_db.* TO 'n8n_workflow'@'%';
4FLUSH PRIVILEGES;

Credential Sharing (Teams)

n8n Sharing Options:

Text
1CREDENTIAL ACCESS LEVELS
2────────────────────────
3
4PRIVATE (Default):
5└── Only creator can use
6
7SHARED WITH USERS:
8├── Specific team members
9└── Can use in their workflows
10
11SHARED GLOBALLY:
12├── All workspace users
13└── Be careful with this!

Setting Up Shared Credentials:

Text
11. Create credential
22. Click Share button
33. Add specific users
44. Set permission level:
5 - Use only (can't see values)
6 - Full access (can edit)

External Secret Management

Environment Variables:

yaml
1# docker-compose.yml
2services:
3 n8n:
4 environment:
5 # Reference from .env
6 - OPENAI_API_KEY=${OPENAI_API_KEY}
7 - STRIPE_API_KEY=${STRIPE_API_KEY}

HashiCorp Vault Integration:

Bash
1# Fetch secrets at startup
2#!/bin/bash
3export OPENAI_API_KEY=$(vault kv get -field=key secret/n8n/openai)
4export STRIPE_API_KEY=$(vault kv get -field=key secret/n8n/stripe)
5
6docker compose up -d

AWS Secrets Manager:

Bash
1# fetch-secrets.sh
2#!/bin/bash
3
4# Fetch from AWS Secrets Manager
5export OPENAI_API_KEY=$(aws secretsmanager get-secret-value \
6 --secret-id n8n/openai \
7 --query SecretString \
8 --output text | jq -r .api_key)
9
10export DB_PASSWORD=$(aws secretsmanager get-secret-value \
11 --secret-id n8n/database \
12 --query SecretString \
13 --output text | jq -r .password)

Docker Secrets:

yaml
1# docker-compose.yml
2version: "3.8"
3
4services:
5 n8n:
6 image: n8nio/n8n
7 secrets:
8 - openai_key
9 - stripe_key
10 environment:
11 # Read from file
12 - OPENAI_API_KEY_FILE=/run/secrets/openai_key
13
14secrets:
15 openai_key:
16 file: ./secrets/openai.txt
17 stripe_key:
18 file: ./secrets/stripe.txt

Backup & Export Credentials

Export Encrypted (Safe):

Bash
1# Credentials stay encrypted with your key
2docker exec n8n n8n export:credentials --all \
3 --output=/backup/credentials.json
4
5# Restore on same instance (same encryption key)
6docker exec n8n n8n import:credentials \
7 --input=/backup/credentials.json

Export Decrypted (Careful!):

Bash
1# WARNING: Contains plain text secrets!
2docker exec n8n n8n export:credentials --all --decrypted \
3 --output=/backup/credentials-plain.json
4
5# Encrypt the file immediately
6gpg --symmetric --cipher-algo AES256 /backup/credentials-plain.json
7
8# Secure delete original
9shred -u /backup/credentials-plain.json

Credential Audit

Audit Script:

Bash
1#!/bin/bash
2# audit-credentials.sh
3
4echo "=== N8N Credential Audit ==="
5echo "Date: $(date)"
6echo ""
7
8# List all credentials
9docker exec n8n n8n credential:list 2>/dev/null | while read line; do
10 echo "$line"
11done
12
13# Check last used (requires custom query)
14echo ""
15echo "=== Usage Statistics ==="
16docker exec n8n-postgres psql -U n8n -d n8n -c "
17SELECT
18 c.name,
19 c.type,
20 COUNT(e.id) as usage_count,
21 MAX(e.\"startedAt\") as last_used
22FROM credentials_entity c
23LEFT JOIN execution_entity e ON e.\"workflowData\"::text LIKE '%' || c.id || '%'
24GROUP BY c.id, c.name, c.type
25ORDER BY last_used DESC NULLS LAST;
26"

Cleanup Unused Credentials:

SQL
1-- Find credentials not used in any workflow
2SELECT c.id, c.name, c.type
3FROM credentials_entity c
4WHERE c.id NOT IN (
5 SELECT DISTINCT jsonb_array_elements(w.nodes)->>'credentials'->>'id'
6 FROM workflow_entity w
7);
8
9-- Manual review before deletion!

Credential Security Checklist

Text
1MONTHLY SECURITY REVIEW
2───────────────────────
3
4□ Review all credentials in n8n
5□ Check for unused credentials → Remove
6□ Verify permissions are minimal
7□ Rotate keys older than 90 days
8□ Update OAuth tokens if needed
9□ Check for revoked/expired keys
10□ Review shared credential access
11□ Audit credential usage logs
12□ Verify encryption key is backed up
13□ Test credential backup/restore

Troubleshooting

"Credentials not found" Error:

Text
1Causes:
21. Credential deleted
32. Permission removed
43. Wrong environment
5
6Fix:
71. Check credential exists
82. Verify workflow has access
93. Re-authenticate OAuth if expired

OAuth Token Expired:

Text
11. Go to credential settings
22. Click "Reconnect"
33. Re-authenticate
44. Save credential

Import Failed:

Text
1Causes:
21. Different encryption key
32. Corrupt JSON file
43. Version mismatch
5
6Fix:
71. Ensure same N8N_ENCRYPTION_KEY
82. Validate JSON syntax
93. Match n8n versions

Bài Tập Thực Hành

Credentials Challenge

Implement secure credential management:

  1. Audit all existing credentials
  2. Create naming convention document
  3. Setup least-privilege database users
  4. Configure credential sharing policy
  5. Implement backup procedure
  6. Schedule monthly credential review

Secure your automation! 🔐

Key Takeaways

Remember
  • 🔑 Least privilege - Only needed permissions
  • 📝 Document - What each credential is for
  • 🔄 Rotate regularly - 90 days max
  • 💾 Backup encrypted - Never plain text
  • 👥 Audit sharing - Who has access?
  • 🧹 Clean up - Remove unused credentials

Tiếp Theo

Bài tiếp theo: User Management - Multi-user setup, invitations, và team organization.