All sensitive user data (Vercel tokens, v0 API keys) are encrypted before being stored in the database using AES encryption.
-
Environment Variable (Required) Add to your
.envfile:ENCRYPTION_SECRET_KEY=your-super-secret-encryption-key-change-this-in-productionImportant:
- Use a strong, random key in production
- Never commit this key to version control
- Generate using:
openssl rand -base64 32or similar
When a user saves their tokens (during onboarding or profile update):
- Tokens are encrypted using AES-256
- Only encrypted data is stored in the database
- Encryption happens in
/api/auth/profileroute
When tokens are needed for API calls:
- Use the
getUserTokens()helper fromlib/supabase/tokens.ts - Tokens are decrypted on-the-fly
- Decrypted values are never stored, only used in memory
import { getUserTokens, getVercelToken, getV0ApiKey } from '@/lib/supabase/tokens'
// Get both tokens
const { vercelToken, v0ApiKey } = await getUserTokens()
// Or get individually
const vercelToken = await getVercelToken()
const v0ApiKey = await getV0ApiKey()import { encrypt } from '@/lib/encryption'
// In your API route
const encryptedToken = encrypt(plainTextToken)
// Save to database
await supabase
.from('profiles')
.update({ vercel_token: encryptedToken })lib/encryption.ts- Core encryption/decryption utilitieslib/supabase/tokens.ts- Helper functions to get decrypted tokensapp/api/auth/profile/route.ts- Encrypts tokens on saveapp/onboarding/page.tsx- Saves encrypted tokens during onboarding
- Never log decrypted tokens - Always sanitize logs
- Use tokens in memory only - Don't store decrypted values
- Rotate encryption key periodically - Follow your security policy
- Use different keys per environment - Dev, staging, prod should have unique keys
- Tokens encrypted at rest in database
- Encryption key stored in environment variable
- Helper functions for secure token retrieval
- Tokens only decrypted when needed
- Add encryption key rotation mechanism (future enhancement)
- Add audit logging for token access (future enhancement)