Multi-Factor Authentication Integration

Introduction

Welcome to the third lesson of the "Multi-Factor Authentication (MFA) in FastAPI" course! In this lesson, we will focus on integrating MFA into a FastAPI application. Building on the foundational concepts from the previous lesson, we will explore the practical steps necessary to enhance the security of your application by implementing MFA. Let's dive in and see how we can secure our application with MFA!

Secure MFA Integration Patterns

Now that you're familiar with the core MFA functions like generate_secret, verify_token, and generate_backup_codes, let's focus on integrating these functions securely into your FastAPI application. Proper integration is crucial - even with well-implemented MFA functions, vulnerabilities can arise from insecure application design. We'll examine how to store MFA data securely, protect sensitive endpoints, and create a robust authentication flow.

Security Reminder:

  • Always encrypt MFA secrets at rest to prevent attackers from accessing them if your database is compromised. Important: Unlike passwords, MFA secrets must be encrypted (not hashed) because they must be retrieved for token verification. Encryption is reversible, which is necessary for TOTP to work.
  • Always hash backup codes before storing them, just like passwords, so they cannot be used if leaked. Backup codes can be hashed because they're compared directly like passwords (the user enters the code, you hash it and compare to stored hash).
  • Implement rate-limiting on all sensitive endpoints (such as /verify, /login, and /login/verify) to protect against brute-force attacks.

The Vulnerable Code

Let's examine a scenario where MFA is not properly integrated, leading to potential security vulnerabilities:

Python
from fastapi import APIRouter, HTTPException
import pyotp

router = APIRouter()

# Example of a vulnerable MFA setup
@router.post('/verify')
async def verify_mfa(username: str, token: str):
    user = await User.find_by_username(username)
    totp = pyotp.TOTP(user.mfa_secret)
    is_valid = totp.verify(token)
    if is_valid:
        user.mfa_enabled = True
        await user.save()
        return {"success": True}
    else:
        return {"success": False, "error": "Invalid token"}

This code contains several critical vulnerabilities:

  • No authentication checks - anyone can access this endpoint
  • No validation that the user exists before accessing properties
  • No protection against brute force attacks
  • The endpoint updates user settings without proper authorization
Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal