A production-ready, secure credential vault built with Next.js 14, TypeScript, Supabase, and end-to-end encryption.
- 🔐 End-to-End Encryption: AES-256-GCM encryption at the application level
- 🔑 Master Password Protection: Separate master password required even with OAuth login
- 🛡️ Row Level Security: Database-level access control via Supabase RLS
- 🔍 Advanced Search: Full-text search across titles, URLs, and tags
- 🏷️ Tag System: Organize credentials with custom tags
- 📊 Audit Logging: Track all view/copy operations
- 🔒 Auto-Lock: Automatic vault locking after inactivity
- 📱 Responsive Design: Works on desktop, tablet, and mobile
- 🌙 Dark Mode: System preference + manual toggle
- ⚡ Server Components: Optimized performance with Next.js 14
- Framework: Next.js 14 (App Router)
- Language: TypeScript
- Database & Auth: Supabase (PostgreSQL + Auth)
- Styling: Tailwind CSS + shadcn/ui
- Encryption: AES-256-GCM (Node.js crypto)
- Node.js 18+ and npm/yarn/pnpm
- Supabase account and project
- OpenSSL (for generating encryption keys)
git clone <repository-url>
cd PasswordManager
npm install- Create a new Supabase project at supabase.com
- Go to SQL Editor and run the schema from
sql/vault_schema.sql - Enable Google OAuth in Authentication > Providers (optional)
- Get your project URL and API keys from Settings > API
# Generate a 32-byte hex encryption key
openssl rand -hex 32IMPORTANT: Save this key securely. If lost, all encrypted data cannot be decrypted.
Create a .env.local file in the root directory:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key
VAULT_ENCRYPTION_KEY=your_64_character_hex_key_from_step_3
NODE_ENV=developmentSecurity Notes:
- Never commit
.env.localto version control - The
VAULT_ENCRYPTION_KEYis critical - store it securely - In production, use environment variables from your hosting provider
The app uses shadcn/ui components. Install them via CLI:
npx shadcn-ui@latest add button
npx shadcn-ui@latest add input
npx shadcn-ui@latest add card
npx shadcn-ui@latest add dialog
npx shadcn-ui@latest add table
npx shadcn-ui@latest add badgenpm run devOpen http://localhost:3000 in your browser.
All database tables are prefixed with vault_:
vault_users- Extended user profiles with master password hashesvault_credentials- Encrypted credentialsvault_tags- Tag definitionsvault_credential_tags- Many-to-many credential-tag relationshipsvault_audit_logs- Audit trail for sensitive operations
- Open Supabase Dashboard
- Go to SQL Editor
- Copy and paste the contents of
sql/vault_schema.sql - Run the script
The schema includes:
- UUID primary keys
- Foreign key constraints
- Indexes for performance
- Row Level Security (RLS) policies
- Triggers for
updated_attimestamps
- Algorithm: AES-256-GCM (authenticated encryption)
- Key Management: Environment variable (32-byte hex)
- IV Generation: Cryptographically secure random per encryption
- Storage Format: Base64-encoded (IV + AuthTag + Ciphertext)
Critical: The encryption key must be:
- Stored securely (never in code)
- Rotated periodically (see Key Rotation below)
- Backed up securely (losing it = losing all data)
- Hashing: bcrypt with 12 rounds
- Storage: Hashed in
vault_userstable - Verification: Required even for OAuth users
- Session: Stored in HTTP-only cookie (server-side)
All tables have RLS policies ensuring users can only access their own data:
-- Example policy
CREATE POLICY "Users can view own credentials"
ON vault_credentials FOR SELECT
USING (auth.uid() = user_id);- Login attempts: 5 per 15 minutes per IP
- Master password: 10 per 15 minutes per user
- Decryption: 10 per minute per user
- Credential creation: 50 per hour per user
- Default timeout: 15 minutes of inactivity
- Configurable via
VAULT_AUTO_LOCK_TIMEOUT_MSenvironment variable - Client-side activity tracking
- Server-side session invalidation
If you need to rotate the encryption key:
- Backup all data - Export credentials (they'll need re-encryption)
- Generate new key:
openssl rand -hex 32 - Update environment variable with new key
- Re-encrypt all credentials:
- Fetch all credentials
- Decrypt with old key
- Encrypt with new key
- Update in database
Warning: This is a complex operation. Test in development first.
If a user forgets their master password:
- Data cannot be recovered - This is by design for security
- User must reset:
- Delete their
vault_usersrecord - Delete all their credentials (or they'll be orphaned)
- User sets new master password on next login
- Delete their
Alternative: Implement a recovery flow with backup encryption keys (advanced, not included).
- Push code to GitHub
- Import project in Vercel
- Add environment variables in Vercel dashboard
- Deploy
The app is a standard Next.js application and can be deployed to:
- Vercel
- Netlify
- AWS Amplify
- Railway
- Any Node.js hosting
Environment Variables: Ensure all variables from .env.local are set in your hosting platform.
- Encryption key set and secure
- Supabase RLS policies enabled
- HTTPS enabled (required for secure cookies)
- Environment variables configured
- Database backups configured
- Rate limiting tested
- Auto-lock timeout configured
- Console logs disabled (handled by
next.config.js)
/app
/(auth) # Authentication pages
/(vault) # Vault dashboard pages
/api # API routes
/lib
encryption.ts # AES-256-GCM encryption
supabase.ts # Supabase clients
auth.ts # Master password management
security.ts # Security utilities
types.ts # TypeScript types
/components
/vault # Vault-specific components
/ui # shadcn/ui components
/sql
vault_schema.sql # Database schema
middleware.ts- Route protection and auth checksapp/(vault)/actions.ts- Server actions for CRUD operationslib/encryption.ts- Encryption/decryption logiclib/auth.ts- Master password verification
- Never log secrets - Console logs are disabled in production
- Use HTTPS - Required for secure cookies
- Rotate keys - Periodically rotate encryption keys
- Monitor audit logs - Review
vault_audit_logsregularly - Backup database - Regular backups of Supabase database
- Keep dependencies updated - Regular security updates
- Use strong master passwords - Minimum 12 characters enforced
This is expected in development if you haven't set the key. Set it in .env.local or use the dev fallback (insecure, development only).
The vault auto-locks after inactivity. Enter your master password to unlock.
- Check Supabase dashboard > Authentication > Providers
- Ensure redirect URL is configured correctly
- Check browser console for errors
- Verify Supabase URL and keys in
.env.local - Check Supabase project status
- Ensure RLS policies are set up correctly
This project is private and proprietary.
For issues and questions, please contact the development team.
Security Notice: This application handles sensitive credentials. Use at your own risk. Always follow security best practices and keep dependencies updated.