This module provides 2FA functionality for enhanced security. It allows users to enable or disable 2FA, generate a QR code for setup in authentication apps, and validate a 2FA code during login.
Step 1: User installs an authentication app on his prefered device.
Step 2: OTP link is generated on a server side.
Step 3: User scans generated on UI QR Code (via app) or follows a link to an authenticator app.
Step 4: User enters code generated by authenticator app and submits its 2FA setup request.
Usage:
Step 1: User logs in with their credentials (username/password).
Step 2: After successful login, the user is prompted to enter a time-based one-time password (TOTP) generated by an authentication app (e.g., Google Authenticator, Authy).
Step 3: The TOTP is verified on the server, and access is granted if both the password and the 2FA code are correct.
Implementation
Intercode Common uses separate UI components and a NestJS module in 2FA implementation
Libraries and enviroment setup
First of all we need to install libraries needed to implement 2FA functionality
yarnaddotplibyarnaddqrcode
Then we need to set up our 2FA App name on a API side
The TwoFactorAuthController handles 2FA-related HTTP requests. This controller is secured with JWT-based authentication and uses the following endpoints:
GET /2fa/generate-qr
Generates a QR code and provides an OTP URI link for the user to set up 2FA in an authentication app. Requires DemoGuard.
POST /2fa/enable-two-factor-auth
Enables 2FA for the user by verifying the provided OTP code. If the code is valid, 2FA is enabled. Requires DemoGuard.
POST /2fa/disable-two-factor-auth
Disables 2FA for the user.
POST /2fa/authenticate
Authenticates the user using their OTP code from an authentication app. If successful, it returns a signed-in token.
Guards Used:
JwtAuthenticationGuard: Ensures that requests come from authenticated users.
DemoGuard: Additional security check applied to 2FA endpoints.
The TwoFactorAuthService is responsible for 2FA logic, including generating secrets, creating QR codes, verifying OTP codes, and handling token generation. Key methods include:
generateTwoFactorAuthSecret(user: JwtUserPayload)
Creates a 2FA secret for the user and stores it in the database. Returns the secret and an OTP URI link if the QR code hasn’t already been generated.
generateQrCode(otpPathUrl: string)
Converts the OTP URI to a QR code (as a data URL) that the user can scan in their authentication app.
activationOfTwoFactorAuth(user: JwtUserPayload, status: boolean)
Activates or deactivates 2FA for the user, based on the status parameter.
verifyTwoFactorAuthCode(code: string, user: JwtUserPayload)
Verifies the provided OTP code against the user’s saved 2FA secret.
signIn(user: JwtUserPayload, isTwoFactorAuthenticated: boolean): Promise<UserTokens>
Generates an access token and refresh token, including the 2FA status, for an authenticated user.
TwoFactorAuth manages 2FA activation and deactivation, integrating with the backend service to display and validate OTP codes and QR codes. It also includes error handling via notifications.
States:
loading: Indicates whether a request is in progress.
qrCode & otpLink: Store the generated QR code data and OTP URI link.
Handlers:
getQrCode: Fetches a QR code for 2FA setup, which the user scans with their authentication app.
handleDisable: Prompts the user to confirm 2FA deactivation, using a modal for confirmation.
turnOffTwoFactorAuth: Deactivates 2FA for the user by calling disableTwoFactorAuth and updating the UI.
onFormSubmit: Submits the OTP code from the TwoFactorAuthForm to enable 2FA.
errorNotification: Shows error messages if any request fails, using Ant Design’s notification system.
Display Logic:
2FA Setup (when currentUser.isTwoFactorEnable is false): Presents three steps:
Step 1: General instructions.
Step 2: QR code generation.
Includes a button to generate the QR code and display it.
The QR code can be scanned to configure the 2FA app.
Step 3: Form for OTP input.
2FA Deactivation (when currentUser.isTwoFactorEnable is true): Shows a button to turn off 2FA with a power icon and loading state, triggering handleDisable.
TwoFactorAuthForm is a form component that accepts a 6-digit OTP code from the user, validating it against predefined rules before submission. It includes:
Code Input Field: Accepts a 6-digit OTP code.
Validation Rules: The code must be exactly 6 digits and is required.
Debounced Validation: Provides feedback 1 second after the user stops typing.
Buttons:
Cancel Button: Allows the user to go back or cancel the 2FA setup, visible based on showCancel prop.
Submit Button: Submits the form to verify and enable 2FA, with a loading indicator when loading is true.