Multi-factor Authentication (MFA) in FastAPI#
Multi-factor Authentication (MFA) is a security mechanism that requires users to verify their identity using multiple factors. These factors are typically categorized into:
Something you know: A password or PIN.
Something you have: A smartphone or a hardware token.
Something you are: Biometrics, such as a fingerprint or facial recognition.
By combining multiple factors, MFA significantly reduces the risk of unauthorized access, even if one factor (e.g., a password) is compromised.
Advantages of MFA: - Enhanced Security: Even if passwords are stolen, attackers cannot access the system without the additional authentication factor. - Reduced Risk of Identity Theft: MFA makes it harder for attackers to impersonate users. - Compliance with Regulations: Many industries require MFA to comply with standards like GDPR or HIPAA. - User Trust: Implementing MFA shows users that their security is a priority.
This document demonstrates how to implement MFA in a FastAPI application using PyOTP for OTP generation and verification.
👉 New to App-Generator? Sign IN with GitHub or Generate Web Apps in no time (free service).
Overview#
This example uses the following: - FastAPI: For building the web application. - PyOTP: For generating and verifying one-time passwords (OTPs). - Pydantic: For data validation. - SQLite: As the database for simplicity (can be replaced with other DB systems).
Step 1: Install Dependencies#
Install the required Python libraries using pip:
pip install fastapi uvicorn sqlalchemy pyotp sqlite3 pydantic
Step 2: Create the Database#
Define a simple SQLite database to store user data.
from sqlalchemy import create_engine, Column, Integer, String, Boolean from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker Base = declarative_base() engine = create_engine("sqlite:///mfa_demo.db") SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) username = Column(String, unique=True, index=True) password = Column(String) otp_secret = Column(String) # Stores the OTP secret is_otp_verified = Column(Boolean, default=False) Base.metadata.create_all(bind=engine)
Step 3: Implement MFA Logic#
Register Users: Allow users to register and generate a unique OTP secret.
Login: Validate username and password, and then request OTP.
Verify OTP: Verify the OTP provided by the user.
from fastapi import FastAPI, Depends, HTTPException from sqlalchemy.orm import Session import pyotp app = FastAPI() def get_db(): db = SessionLocal() try: yield db finally: db.close() @app.post("/register") def register_user(username: str, password: str, db: Session = Depends(get_db)): otp_secret = pyotp.random_base32() new_user = User(username=username, password=password, otp_secret=otp_secret) db.add(new_user) db.commit() db.refresh(new_user) return {"message": "User registered!", "otp_secret": otp_secret} @app.post("/login") def login_user(username: str, password: str, db: Session = Depends(get_db)): user = db.query(User).filter(User.username == username).first() if not user or user.password != password: raise HTTPException(status_code=400, detail="Invalid credentials") return {"message": "Login successful, provide OTP"} @app.post("/verify-otp") def verify_otp(username: str, otp: str, db: Session = Depends(get_db)): user = db.query(User).filter(User.username == username).first() if not user: raise HTTPException(status_code=404, detail="User not found") totp = pyotp.TOTP(user.otp_secret) if not totp.verify(otp): raise HTTPException(status_code=400, detail="Invalid OTP") user.is_otp_verified = True db.commit() return {"message": "OTP verified successfully"}
Step 4: Test the Application#
Start the Application: Run the FastAPI application using Uvicorn:
uvicorn main:app --reload
Register a User: Use a tool like Postman or cURL to register a new user:
POST /register { "username": "testuser", "password": "securepassword" }
Response:
{ "message": "User registered!", "otp_secret": "JBSWY3DPEHPK3PXP" }
Use the otp_secret to set up an OTP generator, such as Google Authenticator.
Login: Authenticate the user using their username and password:
POST /login { "username": "testuser", "password": "securepassword" }
Response:
{ "message": "Login successful, provide OTP" }
Verify OTP: Verify the OTP provided by the user:
POST /verify-otp { "username": "testuser", "otp": "123456" }
Response:
{ "message": "OTP verified successfully" }
Conclusion#
This demonstrates a simple implementation of Multi-factor Authentication (MFA) in FastAPI. For production-grade applications, ensure to use encrypted passwords (e.g., bcrypt) and secure storage mechanisms for secrets and sensitive data.
Links#
👉 New to App-Generator? Join our 10k+ Community using GitHub One-Click SignIN.
👉 Download products and start fast a new project
👉 Bootstrap your startUp, MVP or Legacy project with a custom development sprint