Authentication & MFA
Detailed guide to platform authentication protocols, Twilio Multi-Factor SMS flow, and secure fallback email verification.
Authentication Architecture
HubNest CRM implements stateless security tokens using JSON Web Tokens (JWT). The tokens are partitioned into two tiers:
- Access Token: Short-lived token (15-minute expiration) sent via an
Authorization: Bearer <token>HTTP header or read from secure client cookies. - Refresh Token: Long-lived token (7-day expiration) stored inside an HTTPOnly, secure cookie to request new access tokens.
Multi-Factor Authentication (MFA) Flow
For administrative roles (Super Admin, Admin, and Finance Manager), MFA is enabled by default. The system orchestrates authentication steps via SMS and email channels:
sequenceDiagram
actor User as User Client
participant API as Backend Server
participant Twilio as Twilio API
participant Resend as Email Provider
User->>API: Post /api/auth/login (Credentials)
API-->>User: returns { status: "MFA_PENDING", userId }
alt SMS Verification (Twilio)
API->>Twilio: Dispatch 6-digit OTP code via SMS
Twilio-->>User: SMS arrives at phone
else Fallback Email Delivery (SMTP/Resend)
API->>Resend: Dispatch 6-digit OTP code via email
Resend-->>User: Email arrives in inbox
end
User->>API: Post /api/auth/verify-otp (OTP Code + userId)
API-->>User: returns Access Token + Refresh Token
Step-by-Step MFA Operations
1. Credentials Submission
The user enters their email and password on /auth/login. The server verifies the cryptographic password hash:
const isValid = await bcrypt.compare(password, user.password_hash);
If valid, the server checks if the user has mfa_enabled active. If enabled, it generates a random 6-digit verification code and saves it to Redis with a 5-minute (300 seconds) expiration:
const otp = Math.floor(100000 + Math.random() * 900000).toString();
await redis.set(`otp:${userId}`, otp, 'EX', 300);
2. SMS OTP Dispatch
The server calls the Twilio REST API to dispatch the code:
await twilio.messages.create({
body: `Your HubNest CRM authorization code is: ${otp}. Valid for 5 minutes.`,
from: process.env.TWILIO_PHONE_NUMBER,
to: user.phone
});
3. Automatic Email Fallback
If the Twilio API returns a gateway timeout or delivery status failure:
- The server catches the exception.
- It generates a fallback email dispatch task.
- The server calls Resend (or SMTP) to deliver the OTP directly to the user's inbox:
await resend.emails.send({
from: 'security@hubnest.com',
to: user.email,
subject: 'HubNest CRM - Your Authentication OTP Code',
html: `<p>Your verification code is: <strong>${otp}</strong>.</p>`
});
4. Code Verification
The user enters the code on /auth/verify-otp. The server reads the code from Redis:
- If the values match, it invalidates the OTP key and issues the JWT token suite.
- If it fails, a warning counter is updated in Redis. If a user enters an incorrect OTP 5 times consecutively, the account is temporarily locked for 1 hour to prevent brute-force attacks.