Operations
Security
This page documents the security architecture in OrcaPulse: JWT authentication, password hashing, two-factor authentication, OAuth providers, AES-256 encryption, OTP verification, credit-based authorization, and error logging.
What security covers
OrcaPulse implements multiple layers of security across authentication, encryption, and access control. The system uses JWT-based stateless authentication, bcrypt password hashing, TOTP-based two-factor authentication, AES-256-CBC encryption for secrets and tokens, five OAuth provider integrations, and OTP-based email verification with attempt limiting.
Security enforcement happens at the middleware layer. The protect middleware verifies JWT tokens on every authenticated request, while the adminOnly middleware gates admin routes by role. Sensitive model fields like passwords, tokens, and secrets are excluded from query results by default using Mongoose select: false.
Authentication
OrcaPulse uses JWT Bearer token authentication. When a user logs in or registers, the server generates a signed JWT containing the user ID, email, and role. This token is sent in the Authorization header on every subsequent request and verified by the protect middleware before any controller logic executes.
Tokens expire after seven days. For impersonation sessions, the JWT also carries the impersonating admin's ID so actions are traceable back to the actual operator. The authentication flow supports both standard email/password login and OAuth-based sign-in through multiple providers.
JWT authentication
Bearer token authentication with 7-day expiration, middleware-enforced route protection, and role-based access control for admin endpoints.
Two-factor auth
TOTP-based two-factor authentication with QR code setup, encrypted secret storage, and time-window tolerance for code verification.
AES-256 encryption
Secrets, API keys, OAuth tokens, and 2FA codes are encrypted at rest using AES-256-CBC with random initialization vectors per record.
- JWT signing: tokens are signed with a server-side secret and verified on every authenticated request.
- Bearer scheme: tokens are passed via the Authorization header using the Bearer scheme.
- Seven-day expiry: tokens expire after seven days, requiring re-authentication.
- Impersonation tokens: carry both the target user ID and the admin's ID for audit purposes.
Password hashing
Passwords are hashed using bcrypt before being stored in the database. The User model uses a pre-save hook that automatically hashes the password field whenever it is modified, so plaintext passwords never reach the database.
Password verification uses bcrypt.compare() during login, which is resistant to timing attacks. The password field is configured with select: false on the Mongoose schema, so it is never included in query results unless explicitly requested. Minimum password length is six characters.
- bcrypt hashing: industry-standard slow hash function resistant to brute force and rainbow table attacks.
- Automatic hashing: pre-save hook ensures passwords are always hashed before database writes.
- Hidden by default: the password field is excluded from all query results unless explicitly selected.
Two-factor authentication
OrcaPulse supports TOTP-based two-factor authentication using the speakeasy library. Users set up 2FA by scanning a QR code generated by the platform, then verifying a code to confirm the setup. Once enabled, login requires both the password and a valid TOTP code.
The 2FA secret is encrypted using AES-256-CBC before storage. During setup, a temporary encrypted secret is stored with a ten-minute expiration. After verification, the secret moves to permanent encrypted storage. Disabling 2FA requires a valid TOTP code to prevent unauthorized changes.
- TOTP standard: time-based one-time passwords compatible with authenticator apps like Google Authenticator and Authy.
- QR code setup: QR codes are generated server-side for easy authenticator app enrollment.
- Encrypted secrets: 2FA secrets are encrypted at rest using AES-256-CBC with per-record initialization vectors.
- Window tolerance: code verification allows a one-window tolerance to account for clock skew between devices.
OAuth providers
OrcaPulse supports sign-in through five OAuth providers: Google, Microsoft, GitHub, Apple, and Facebook. Each provider is implemented with its own controller, callback handling, and user account linking. The Google integration also supports Gmail OAuth for email sending with encrypted token storage.
| Provider | Features |
|---|---|
| Sign-in, Gmail integration with encrypted refresh tokens, PKCE support | |
| Microsoft | Sign-in with Microsoft accounts via OAuth2 authorization flow |
| GitHub | Sign-in with GitHub accounts for developer-oriented users |
| Apple | Sign in with Apple for iOS and web-based authentication |
| Sign-in with Facebook accounts for social-first users |
- State parameter validation: OAuth flows include state parameter encoding with origin validation to prevent CSRF attacks.
- Provider ID tracking: each user stores provider-specific IDs (googleId, microsoftId, etc.) to prevent duplicate account linking.
- Last login method: the system tracks which OAuth provider was used for the most recent sign-in.
- Token encryption: OAuth refresh tokens for integrations like Gmail are encrypted before database storage.
Encryption
OrcaPulse uses AES-256-CBC encryption for sensitive data at rest. This includes 2FA secrets, integration API keys for third-party providers, and OAuth refresh tokens. Each encrypted value uses a randomly generated 16-byte initialization vector, stored alongside the ciphertext in the format iv_hex:encrypted_hex.
The encryption key is derived from an environment variable and truncated to 32 characters for AES-256 compatibility. Decryption is implemented with safe error handling that returns null on failure rather than throwing, so corrupted or incorrectly encrypted values do not crash the application.
- AES-256-CBC: 256-bit encryption in cipher block chaining mode, an industry-standard symmetric encryption algorithm.
- Random IVs: each encryption operation generates a fresh random initialization vector, preventing identical plaintexts from producing identical ciphertexts.
- Integration secrets: API keys for providers like ElevenLabs, Deepgram, OpenAI, and HubSpot are encrypted before storage.
- Safe decryption: decryption errors are handled gracefully with null returns instead of application crashes.
OTP and email verification
OrcaPulse uses six-digit one-time passwords for email verification during signup, password reset requests, and account deletion confirmations. OTPs are generated and stored with a ten-minute expiration, automatic cleanup of expired codes, and a maximum of five failed verification attempts before the OTP is invalidated.
Rate limiting on OTP generation prevents abuse by blocking new OTP requests within one minute of a previous request. Expired OTPs are automatically purged every five minutes through a cleanup process.
- Ten-minute expiry: OTPs are valid for ten minutes after generation.
- Attempt limiting: five failed verification attempts invalidate the OTP, requiring a new one.
- Rate limiting: minimum one-minute gap between OTP generation requests.
- Automatic cleanup: expired OTPs are purged every five minutes.
Error handling and logging
The platform includes a centralized error handler middleware that catches and logs errors to a database collection. Each error record includes the request IP, user agent, authenticated user ID, request path, error message, and stack trace. Error persistence is non-blocking so logging failures do not affect the response.
The error handler also normalizes common Mongoose errors (validation errors, duplicate key errors, and invalid ID cast errors) into consistent HTTP responses, preventing raw database error details from leaking to clients.
- Database logging: errors are persisted to an ErrorLog collection with full request context.
- Error normalization: Mongoose validation, duplicate key, and cast errors are mapped to clean HTTP responses.
- Non-blocking persistence: error logging is fire-and-forget so it does not delay the error response.
- Sensitive field hiding: model fields marked with
select: falseare excluded from all responses by default.
Current project shape
The security implementation is functional and covers the core requirements: JWT authentication, bcrypt password hashing, TOTP 2FA, AES-256 encryption, five OAuth providers, OTP verification with rate limiting, credit-based authorization, and centralized error logging.
Areas that could be strengthened in the future include general API rate limiting beyond OTP-specific controls, additional security headers via a library like Helmet, migration of OTP storage from in-memory to a persistent store like Redis, JWT refresh token rotation, and input sanitization for HTML and XSS protection.
Next steps
After Security, the next useful Operations page is Billing and Plans, which documents how the credit system, Stripe integration, and plan management work together to gate and fund platform operations.



