In this lesson, you will learn how to implement TOTP (Time-based One-Time Password) secondary authentication to protect sensitive actions like changing security settings or performing financial transactions in your Node.js application.
Beyond the Initial Login
While OAuth2 handles the initial user identity verification, Multi-Factor Authentication (MFA) adds a layer of assurance for "critical actions." Even if an attacker possesses a user's session token, they cannot proceed without the dynamic code generated by the user's authenticator app (like Google Authenticator).
The TOTP Workflow
TOTP relies on a shared secret key between your server and the user’s device.
- Enrollment: You generate a secret, store it in the user's record, and display a QR code to the user.
- Verification: When a user triggers a protected action, your server intercepts the request and demands a 6-digit code.
- Validation: You use the shared secret and the current timestamp to recalculate the expected code and compare it against the user's input.
Implementing the Check
In your Node.js controller, you should implement a middleware that triggers only when a sensitive route is hit. If the user hasn't provided a valid TOTP code in their request header, the action is blocked:
// Middleware to protect a critical route
const verifyMfa = async (req, res, next) => {
const { userMfaSecret } = req.user; // Retrieved from DB
const { token } = req.headers; // Provided by user
const isValid = totpLibrary.verify({
token,
secret: userMfaSecret,
window: 1 // Allows for slight clock drift
});
if (!isValid) {
return res.status(403).json({ error: "MFA validation failed" });
}
next();
};
app.post('/api/transfer-funds', verifyMfa, (req, res) => {
// Proceed with sensitive logic
});
Security Considerations
When implementing this, ensure the shared secret is encrypted at rest in your database. Additionally, remember to implement rate limiting on the validation endpoint to prevent brute-force attacks on the 6-digit code. By integrating this into specific sensitive routes rather than just the initial login, you provide defense-in-depth without inconveniencing the user during routine navigation.
Key Takeaway: MFA for critical actions creates a high-assurance boundary that protects users even if their primary session tokens are compromised.