HIGH man in the middlefastapibasic auth

Man In The Middle in Fastapi with Basic Auth

Man In The Middle in Fastapi with Basic Auth — how this specific combination creates or exposes the vulnerability

When Fastapi applications use HTTP Basic Authentication without transport-layer protection, a Man In The Middle (MitM) can intercept credentials and session tokens in clear text. Basic Auth encodes username:password with Base64, which is trivially reversible; encoding is not encryption. If an endpoint serves authenticated content over plain HTTP, or if TLS is misconfigured (for example, terminating TLS at a load balancer without enforcing it on the application), an attacker on the same network can capture the Authorization header and reuse it to impersonate the victim.

In a typical Fastapi service using Basic Auth, the framework validates credentials on each request but does not enforce how the request arrived. Consider a service that accepts a bearer-like flow where the decoded credentials are mapped to a session token or cached user object. An MitM who can observe or modify traffic can inject, modify, or replay intercepted Authorization headers to escalate privileges or access other users’ data. This becomes especially critical when the same credentials are reused across multiple endpoints without additional protections like nonce or timestamp validation. The risk is compounded when OpenAPI specs describe the endpoint as secure without explicitly requiring HTTPS, because tools like middleBrick can detect mismatches between declared transport security and runtime behavior during unauthenticated scans.

During a black-box scan, middleBrick checks whether authentication-sensitive endpoints are served over TLS and whether responses expose credentials or tokens in logs or error messages. Findings may highlight missing HTTP Strict Transport Security (HSTS), lack of certificate validation in clients, or endpoints that accept both HTTP and HTTPS. Because Basic Auth places the secret in every request, interception of any request reveals the credential; unlike token-based flows, there is no built-in expiration beyond changing the password. Mitigations must therefore focus on enforcing HTTPS, validating TLS configuration, and ensuring that frameworks do not allow fallback to cleartext transport.

Basic Auth-Specific Remediation in Fastapi — concrete code fixes

To secure Fastapi with Basic Auth, enforce HTTPS universally and avoid storing or logging credentials beyond the immediate authentication step. Below are concrete, working examples that combine safe credential handling with transport security checks.

Enforce HTTPS in Fastapi

Use middleware to redirect HTTP to HTTPS and set HSTS headers so browsers never attempt cleartext connections.

from fastapi import Fastapi, Request, HTTPException, status
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware

app = Fastapi()
app.add_middleware(HTTPSRedirectMiddleware)

@app.middleware("http")
async def enforce_https(request: Request, call_next):
    if not request.url.scheme == "https":
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="HTTPS is required"
        )
    response = await call_next(request)
    response.headers["Strict-Transport-Security"] = "max-age=31536000; includeSubDomains"
    return response

Secure Basic Auth with hashed credentials and constant-time comparison

Never compare passwords with plain equality. Store only salted, hashed credentials (for example using passlib with bcrypt) and verify using a constant-time function to mitigate timing attacks.

from fastapi import Depends, Fastapi, Header, HTTPException, status
from passlib.context import CryptContext
import secrets

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

# Example stored hash for user:alice, password:CorrectHorseBatteryStaple
USERS = {
    "alice": {"hash": pwd_context.hash("CorrectHorseBatteryStaple"), "scope": "read write"}
}

def verify_password(plain: str, hashed: str) -> bool:
    return pwd_context.verify(plain, hashed)

def get_current_user(authorization: str = Header(...)):
    # Basic Auth header format: Basic base64(username:password)
    import base64
    if not authorization.startswith("Basic "):
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Invalid authentication scheme")
    try:
        decoded = base64.b64decode(authorization.split(" ")[1]).decode("utf-8")
    except Exception:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid authorization header")
    username, _, password = decoded.partition(":")
    if username not in USERS:
        # Use a dummy hash to keep timing similar
        verify_password(secrets.token_hex(16), USERS["alice"]["hash"])
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect credentials")
    if not verify_password(password, USERS[username]["hash"]):
        raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Incorrect credentials")
    return {"username": username, "scope": USERS[username]["scope"]}

@app.get("/secure/data")
def read_secure(current: dict = Depends(get_current_user)):
    return {"message": f"Hello {current['username']}", "scope": current['scope']}

Complementary protections

  • Always serve API documentation and health checks over HTTPS only.
  • Use HTTP Strict Transport Security (HSTS) with a long max-age and includeSubDomains where applicable.
  • Rotate credentials regularly and avoid embedding secrets in source or Docker images; prefer secrets injected at runtime.
  • Validate and sanitize any data derived from authentication to prevent downstream injection or exposure.
  • Combine with additional checks such as rate limiting and anomaly detection to reduce the impact of credential replay if interception occurs.

With these measures, the combination of Fastapi and Basic Auth remains usable in controlled environments, but teams should evaluate whether token-based flows (for example, OAuth2 with PKCE) provide better lifecycle management and reduced exposure window for secrets.

Frequently Asked Questions

Can middleBrick detect missing HTTPS for Basic Auth endpoints?
Yes. middleBrick scans unauthenticated attack surfaces and flags endpoints that transmit credentials without enforcing HTTPS, including mismatches between declared transport security in OpenAPI specs and runtime behavior.
Is Base64 encoding sufficient protection for credentials in Fastapi Basic Auth?
No. Base64 is an encoding, not encryption. Credentials must be protected by TLS; otherwise, any intermediary can decode the header. Always enforce HTTPS and store passwords as salted hashes, never in plaintext.