Implementing Two-Factor Authentication (2FA) in Node.js with TOTP and Google Authenticator
Two-Factor Authentication (2FA) is an extra layer of security that requires not only a password and username but also something that only the user has on them, typically a one-time code generated by an app like Google Authenticator. This guide walks you through implementing 2FA in a Node.js application using TOTP (Time-based One-Time Password), Google Authenticator, and otplib.
Overview of Two-Factor Authentication (2FA)
2FA enhances security by requiring users to provide a time-based code from a separate device, typically their phone, in addition to their password. This makes it much harder for an attacker to gain access to an account, even if they have the user's password.
How TOTP Works
- TOTP Secret: A unique secret key is generated for each user and stored securely.
- Authenticator App: The user adds this secret to an app like Google Authenticator, which generates a new code every 30 seconds.
- Code Verification: The user provides the current code along with their login details, which the server verifies to complete the login process.
Tools Required
We’ll use the otplib library to generate and verify TOTP codes and qrcode to generate QR codes that can be scanned with Google Authenticator.
Setting Up the Project
We’ll build upon a basic Node.js setup with otplib and qrcode.
Step 1: Install the Required Dependencies
If you’re starting a new project, initialize it and install the necessary packages.
- otplib: To generate and verify TOTP codes.
- qrcode: To generate a QR code for easy setup in Google Authenticator.
Configuring Environment Variables
Create a .env
file to store environment variables, including the JWT secret and MongoDB URI.
Setting Up the User Model with 2FA Fields
Modify the User
model to include fields for storing the 2FA secret and the 2FA enabled status.
models/User.js
Setting Up 2FA Registration and Verification Routes
We’ll create routes to enable 2FA for users, including generating a TOTP secret and verifying TOTP codes.
Step 1: Generate TOTP Secret and QR Code
In the auth.js
route file, create a route to generate a TOTP secret and QR code for the user.
routes/auth.js
In this code:
- TOTP Secret: A unique TOTP secret is generated for the user.
- QR Code: The secret is embedded in a QR code URL for the user to scan with an authenticator app.
Step 2: Verifying the TOTP Code
After setting up 2FA, the user must provide a valid TOTP code from their authenticator app to confirm activation.
routes/auth.js
In this code:
- The user submits the TOTP token (code) generated by their authenticator app.
- If valid,
twoFactorEnabled
is set totrue
, confirming that 2FA is enabled.
Adding 2FA to the Login Process
To secure the login process, add an additional verification step for users with 2FA enabled.
Step 1: Update Login Route to Check for 2FA
Modify the login route to handle users with 2FA enabled.
routes/auth.js
In this modified login route:
- 2FA Check: If 2FA is enabled, the user must provide a valid TOTP token along with their password.
- Token Verification: The token is verified using the user’s TOTP secret.
Testing the 2FA Process
- Enable 2FA: Access the
/enable-2fa
endpoint to generate a QR code and secret for the user. - Scan the QR Code: Use Google Authenticator or a similar app to scan the QR code.
- Verify 2FA: Access the
/verify-2fa
endpoint, submitting a valid TOTP code to enable 2FA. - Log In with 2FA: Test the login route by submitting the email, password, and a valid TOTP code.
Best Practices for 2FA Implementation
- Use a Short Expiration for Tokens: Use short expiration times (e.g., 30 seconds) for TOTP tokens to minimize the risk if compromised.
- Secure Secret Storage: Store TOTP secrets securely in your database and ensure they are protected.
- Offer Backup Codes: Provide backup codes for users in case they lose access to their 2FA app. 4
. Limit Verification Attempts: Implement rate limiting to prevent brute-force attacks on 2FA codes. 5. Allow 2FA Reset: Offer a secure way to reset 2FA for users who have lost access to their authenticator app, usually through identity verification.
Conclusion
Implementing Two-Factor Authentication (2FA) with TOTP and Google Authenticator in a Node.js application enhances security by adding an additional verification layer. By generating a TOTP secret for each user, allowing them to scan it with an authenticator app, and verifying the token during login, you can provide a secure 2FA experience for your users.
Integrate these 2FA techniques into your project to protect user accounts and improve the security of your Node.js application.