Credentials & Security Design
AES-256-GCM encryption, vault architecture, multi-tenant isolation. Complete security guide.
Credential Types
| Type ID | Type Name | Used By | Fields |
|---|---|---|---|
| 1 | PasswordRecord | SMTP | Username, Password |
| 2 | ApiKeyRecord | AWS SES, Custom Providers | ApiKey (and possibly ApiSecret) |
| 3 | OAuth2Record | Gmail | AccessToken, RefreshToken, ExpiresAt |
Database Storage
Credentials stored in AIExt_Credentials table with two components:
- DisplayMetadata: Public configuration (JSON, plaintext) — provider name, host, port, from email
- EncryptedData: Secret data (AES-256-GCM encrypted) — passwords, API keys, tokens
Encryption Architecture
Algorithm: AES-256-GCM
- Cipher: AES-256 (256-bit key)
- Mode: GCM (Galois/Counter Mode) — authenticated encryption
- Key Derivation: Azure Key Vault (or equivalent) manages root keys
- Key Rotation: Supported via
KeyVersionfield
Encryption Process
1. ICredentialEncryptionService.EncryptAsync(plaintext, keyVersion)
2. Generates random IV (96-bit)
3. Encrypts with AES-256-GCM
4. Returns: IV + AuthTag + CiphertextHashDecryption Process
1. ICredentialEncryptionService.DecryptAsync(encryptedData)
2. Extracts IV + AuthTag + Ciphertext
3. Decrypts with AES-256-GCM
4. Validates authentication tag
5. Returns plaintext or exception if invalidMulti-Tenant Isolation
- TenantID: Every credential tied to one tenant
- Named Credentials: Each tenant configures own "email-primary" credential
- Database Index:
IX_AIExt_Credentials_Name_TenantIDensures fast lookup - No Cross-Tenant Leakage:
GetCredentialByNameAsync(name, tenantID)enforces tenant isolation
Security Best Practices
Do's
- ✅ Store all credentials encrypted at rest
- ✅ Use HTTPS for all API calls to external providers
- ✅ Rotate keys regularly via KeyVersion
- ✅ Log credential access attempts (audit trail)
- ✅ Use named credentials, never hardcode secrets
- ✅ Implement rate limiting on credential lookups
Don'ts
- ❌ Never log plaintext credentials
- ❌ Never version control secrets
- ❌ Never pass credentials through query strings
- ❌ Never cache decrypted credentials across requests
- ❌ Never share credentials between tenants
Secret Rotation
If an API key is compromised:
- Generate new API key at provider
- Create new credential with same name in database
- Old credential automatically becomes inactive
- No code changes required
Audit Logging
All credential access is logged with:
- Timestamp of access
- TenantID
- Credential name
- Success/failure
- Error message (if failed)
