hngprojects / hng_boilerplate_nestjs

Description
Apache License 2.0
182 stars 105 forks source link

[FEAT]: Implement Optional Two-Factor Authentication (2FA) #266

Closed chukssomzzy closed 2 weeks ago

chukssomzzy commented 1 month ago

Description

Develop an optional Two-Factor Authentication (2FA) system for our application to enhance account security. This feature will allow users to enable 2FA using Time-based One-Time Passwords (TOTP) generated by authenticator apps like Google Authenticator or Authy. The system should integrate seamlessly with our existing authentication flow and provide a smooth user experience for enabling, using, and disabling 2FA.

Acceptance Criteria

API Endpoints Implementation

  1. Enable 2FA: POST /api/v1/2fa/enable
  2. Verify 2FA: POST /api/v1/2fa/verify
  3. Disable 2FA: POST /api/v1/2fa/disable
  4. Generate Backup Codes: POST /api/v1/2fa/backup-codes
  5. Recover 2FA: POST /api/v1/2fa/recover

All endpoints should accept HTTP POST requests and be accessible only to authenticated users.

Enable 2FA Endpoint

Request Body

{
    "password": "current_password"
}

Success Response (200 OK)

{
    "status_code": 200,
    "message": "2FA setup initiated",
    "data": {
        "secret_key": "JBSWY3DPEHPK3PXP",
        "qr_code_url": "https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=otpauth://totp/App:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=YourApp"
    }
}

Verify 2FA Endpoint

Request Body

{
    "totp_code": "123456"
}

Success Response (200 OK)

{
    "status_code": 200,
    "message": "2FA verified and enabled", 
    "data": {
        "backup_codes": ["98765432", "87654321", "76543210", "65432109", "54321098"]
    }
}

backup_codes is only added if the user is verifying an enabled 2fa.

Disable 2FA Endpoint

Request Body

{
    "password": "current_password",
    "totp_code": "123456"
}

Success Response (200 OK)

{
    "status_code": 200,
    "message": "2FA has been disabled"
}

Generate Backup Codes Endpoint

Request Body

{
    "password": "current_password",
    "totp_code": "123456"
}

Success Response (200 OK)

{
    "status_code": 200,
    "message": "New backup codes generated",
    "data": {
        "backup_codes": ["98765432", "87654321", "76543210", "65432109", "54321098"]
    }
}

Recover Backup Code

Request Body

{
    "backup_codes": "12345"
}

Success Response (200 OK)

{
    "status_code": 200,
    "message": "2fa Verified",
}

Failure Response (for all endpoints)

{
    "status_code": 400,
    "error": "Invalid request",
    "message": "Specific error message"
}

Purpose

Implement an optional Two-Factor Authentication system to enhance account security for users who choose to enable it, providing an additional layer of protection against unauthorized access.

Requirements

  1. Use a secure TOTP algorithm compatible with common authenticator apps.
  2. Generate and store a unique secret key for each user enabling 2FA.
  3. Provide a QR code for easy secret key input into authenticator apps.
  4. Generate one-time backup codes for account recovery.
  5. Update the login flow to require 2FA code input for users with 2FA enabled.
  6. Implement rate limiting on 2FA verification attempts to prevent brute force attacks.
  7. Ensure all 2FA-related data is encrypted at rest and in transit.
  8. Add 2FA status to the user model in the database.
  9. Implement proper error handling and user feedback for all 2FA operations.
  10. Provide clear instructions for users throughout the 2FA setup process.

Expected Outcome

Users can optionally enable 2FA for their accounts, significantly enhancing their account security. The system seamlessly integrates with the existing authentication flow and provides a user-friendly experience for managing 2FA.

Status Codes and Error Responses

200 OK

[Success responses are already defined for each endpoint above]

400 Bad Request

{
    "status_code": 400,
    "error": "Invalid request",
    "message": "Specific error message"
}

Possible specific error messages:

401 Unauthorized

{
    "status_code": 401,
    "error": "Unauthorized",
    "message": "Authentication required"
}

403 Forbidden

{
    "status_code": 403,
    "error": "Forbidden",
    "message": "You do not have permission to perform this action"
}

429 Too Many Requests

{
    "status_code": 429,
    "error": "Too many requests",
    "message": "You have exceeded the rate limit. Please try again in X seconds",
    "data": {
        "retry_after": 300
    }
}

500 Internal Server Error

{
    "status_code": 500,
    "error": "Internal server error",
    "message": "An unexpected error occurred. Please try again later"
}

Additional Error Handling Requirements

  1. Ensure all error responses follow the above format for consistency.
  2. Log detailed error information server-side for debugging, but never expose sensitive details in the response.
  3. For the 429 error, include a "retry_after" value in the response to inform the client when they can retry the request.
  4. Implement proper error handling in the client application to provide user-friendly messages based on these error responses.

Testing

  1. Verify the 2FA setup process, including QR code generation and secret key storage.
  2. Test the TOTP verification process with valid and invalid codes.
  3. Ensure backup codes work correctly for account recovery.
  4. Verify that disabling 2FA removes all associated data.
  5. Test rate limiting on failed 2FA attempts.
  6. Verify that 2FA is correctly enforced during login for users who have enabled it.
  7. Test 2FA functionality across different devices and authenticator apps.
  8. Perform security testing to ensure 2FA cannot be bypassed.
  9. Verify proper error handling and user feedback for all 2FA operations.
  10. Conduct load testing to ensure 2FA doesn't significantly impact system performance.
chukssomzzy commented 1 month ago

This issue is currently implemented by interns

@chukssomzzy - fastapi @rb-isiaq - nestjs