GuardAPI Logo
GuardAPI

Fix Broken User Authentication in FastAPI

FastAPI's flexibility often leads developers to 'roll their own' auth, resulting in catastrophic Broken Authentication (OWASP A01:2021). Common failures include plaintext password comparisons, predictable session tokens, and lack of credential salting. To secure a FastAPI app, you must move away from manual verification and leverage industry-standard cryptographic hashing and signed JWTs.

The Vulnerable Pattern

from fastapi import FastAPI
app = FastAPI()

VULNERABLE: Plaintext storage and static/predictable tokens

users_db = {‘admin’: ‘password123’}

@app.post(‘/login’) async def login(username, password): user_pass = users_db.get(username) if user_pass == password: # Timing attack vulnerable & plaintext leak return {‘token’: ‘admin-token-fixed’} # Static token is replayable forever return {‘error’: ‘Unauthorized’}

The Secure Implementation

The secure implementation mitigates authentication risks through three layers. 1. Password Hashing: Using Passlib with Bcrypt ensures passwords are never stored in plaintext and are resistant to brute-force via salting. 2. Standardized Extraction: OAuth2PasswordBearer handles the extraction of the Authorization header, preventing manual parsing errors. 3. Cryptographic Tokens: Instead of static strings, we use signed JWTs with an 'exp' (expiration) claim. This prevents replay attacks and allows the server to verify the token's integrity without a database lookup for every request. Always set the 'HttpOnly' and 'Secure' flags if passing tokens via cookies.

from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from passlib.context import CryptContext
from jose import jwt
from datetime import datetime, timedelta

SECURE CONFIG

SECRET_KEY = ‘USE_A_STRONG_RANDOM_HEX_STRING_HERE’ ALGORITHM = ‘HS256’ pwd_context = CryptContext(schemes=[‘bcrypt’], deprecated=‘auto’) oauth2_scheme = OAuth2PasswordBearer(tokenUrl=‘token’)

app = FastAPI()

def verify_password(plain, hashed): return pwd_context.verify(plain, hashed)

@app.post(‘/token’) async def login(form_data: OAuth2PasswordRequestForm = Depends()): user = get_user_from_db(form_data.username) if not user or not verify_password(form_data.password, user[‘hashed_password’]): raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=‘Invalid credentials’)

# Issue short-lived JWT
access_token_expires = timedelta(minutes=15)
expire = datetime.utcnow() + access_token_expires
to_encode = {'sub': user['username'], 'exp': expire}
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return {'access_token': encoded_jwt, 'token_type': 'bearer'}</code></pre>
System Alert • ID: 7408
Target: FastAPI API
Potential Vulnerability

Your FastAPI API might be exposed to Broken User Authentication

74% of FastAPI apps fail this check. Hackers use automated scanners to find this specific flaw. Check your codebase before they do.

RUN FREE SECURITY DIAGNOSTIC
GuardLabs Engine: ONLINE

Free Tier • No Credit Card • Instant Report

Verified by Ghost Labs Security Team

This content is continuously validated by our automated security engine and reviewed by our research team. Ghost Labs analyzes over 500+ vulnerability patterns across 40+ frameworks to provide up-to-date remediation strategies.