Skip to content

Multi-Factor Authentication — Complete MFA Implementation Guide

DodaTech Updated 2026-06-28 2 min read

In this tutorial, you will learn about Multi. We cover key concepts, practical examples, and best practices to help you master this topic.

Multi-factor authentication (MFA) requires users to provide two or more verification factors: something you know (password), something you have (phone or hardware key), or something you are (biometric).

What You'll Learn

You'll learn MFA strategies including TOTP, SMS codes, and hardware security keys, and how to implement them in your API.

Why It Matters

MFA blocks 99.9% of automated attacks according to Microsoft. It is required by Compliance standards (PCI DSS, SOC 2, HIPAA) and increasingly mandated by insurance providers.

Real-World Use

A cryptocurrency exchange requires MFA for all withdrawals. The user enters their password and then a time-based code from their authenticator app. Even if the password is phished, the attacker cannot complete the withdrawal without the second factor.

sequenceDiagram
    participant User
    participant API
    User->>API: POST /login (password)
    API->>User: 200 (MFA required, challenge)
    User->>API: POST /mfa/challenge (TOTP code)
    API->>API: Verify TOTP
    API->>User: access_token

Implementation

import pyotp
import qrcode
from flask import Flask, request, jsonify

app = Flask(__name__)

users = {}

@app.route("/api/mfa/setup")
def setup_mfa():
    user_id = get_current_user()
    secret = pyotp.random_base32()
    users[user_id]["totp_secret"] = secret
    totp = pyotp.TOTP(secret)
    provisioning_uri = totp.provisioning_uri(name=f"user-{user_id}", issuer_name="MyAPI")
    return jsonify({"secret": secret, "provisioning_uri": provisioning_uri})

@app.route("/api/mfa/verify", methods=["POST"])
def verify_mfa():
    user_id = get_current_user()
    code = request.json.get("code")
    secret = users[user_id].get("totp_secret")
    totp = pyotp.TOTP(secret)
    if totp.verify(code, valid_window=1):
        users[user_id]["mfa_enabled"] = True
        return jsonify({"message": "MFA enabled"})
    return jsonify({"error": "Invalid code"}), 400

@app.route("/api/login", methods=["POST"])
def login():
    if user["mfa_enabled"]:
        code = request.json.get("mfa_code")
        if not code or not totp.verify(code):
            return jsonify({"error": "MFA required"}), 401
    return jsonify({"token": create_token()})

Common Mistakes

| Mistake | Fix | |---------|-----| | SMS as only MFA method | SMS is vulnerable to SIM swapping; offer TOTP or hardware keys | | No backup codes | Users locked out if they lose their phone | Generate and show backup codes during setup | | MFA fatigue | Attackers spam push notifications | Require number matching or location-based MFA | | Not Rate Limiting MFA attempts | Brute-force TOTP codes | Rate limit MFA verification attempts | | Skipping MFA on API-only clients | APIs need MFA too | Support MFA tokens in Authorization header |

Practice Questions

  1. What are the three types of authentication factors?
  2. How does TOTP work?
  3. Why is SMS MFA considered less secure?
  4. What are backup codes?
  5. How do hardware security keys (FIDO2/WebAuthn) work?

Challenge

Implement TOTP-based MFA for a login API. Include: MFA enrollment, QR Code Generation, code verification, backup codes, and rate limiting on MFA attempts.

What's Next

Learn about passwordless authentication for a frictionless user experience.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro