Insecure Direct Object Reference in Fastapi with Basic Auth
Insecure Direct Object Reference in Fastapi with Basic Auth — how this specific combination creates or exposes the vulnerability
Insecure Direct Object Reference (BOLA/IDOR) occurs when an API exposes internal object references (such as numeric IDs or UUIDs) without verifying that the requesting user is authorized to access that specific resource. In FastAPI, using HTTP Basic Authentication does not inherently protect against IDOR; authentication confirms identity, but authorization must still be enforced for each object access.
When Basic Auth is used in FastAPI, the framework can validate credentials and attach a user identity (e.g., via Depends and an HTTPBasic security scheme), but if route parameters like item_id are used directly to query a database without checking ownership or permissions, the endpoint becomes vulnerable. For example, an authenticated user could iterate through numeric IDs (/items/1, /items/2) and access data belonging to other users because the endpoint lacks per-object authorization checks.
Consider a FastAPI route that retrieves a user’s document by ID using a path parameter without verifying the document belongs to the authenticated subject. Even with valid Basic Auth credentials, the absence of a check such as "does this document_id belong to this user" results in a BOLA/IDOR finding. middleBrick’s checks for BOLA/IDOR include runtime tests that attempt to access objects with known IDs while authenticated as one user, then attempt the same access as another user to detect missing authorization boundaries.
In OpenAPI/Swagger specs, this risk is compounded when path parameters expose internal identifiers without references to authorization constraints in the spec. middleBrick cross-references the spec definitions with runtime behavior; if the spec documents endpoints with user-specific paths but does not describe scope or ownership requirements, the scan highlights a discrepancy that commonly maps to OWASP API Top 10 — Broken Access Control (IDOR).
Real-world attack patterns include authenticated enumeration across sequential IDs, accessing other tenants’ resources in multi-tenant schemas, or leveraging predictable UUIDs to reach private records. Because Basic Auth transmits credentials in an encoded (not encrypted) form unless protected by TLS, exposure risks are higher when endpoints do not enforce strict authorization, making the combination of FastAPI + Basic Auth a common scenario for IDOR findings in unauthenticated black-box scans.
Basic Auth-Specific Remediation in Fastapi — concrete code fixes
To remediate BOLA/IDOR in FastAPI with Basic Auth, you must enforce per-request authorization that ties each object to the authenticated subject. Below are concrete, working code examples that combine HTTP Basic Authentication with ownership checks.
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from pydantic import BaseModel
from typing import Dict
import secrets
app = FastAPI()
security = HTTPBasic()
# In-memory store for demo; replace with a real DB in production
users_db: Dict[str, str] = {"alice": "password1", "bob": "password2"}
items_db: Dict[int, Dict] = {
1: {"owner": "alice", "data": "Alice’s secret"},
2: {"owner": "bob", "data": "Bob’s secret"},
}
class ItemResponse(BaseModel):
item_id: int
data: str
def get_current_user(credentials: HTTPBasicCredentials = Depends(security)):
username = credentials.username
password = credentials.password
if username in users_db and users_db[username] == password:
return username
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Invalid credentials",
headers={"WWW-Authenticate": "Basic"},
)
@app.get("/items/{item_id}", response_model=ItemResponse)
def read_item(
item_id: int,
current_user: str = Depends(get_current_user),
):
item = items_db.get(item_id)
if item is None:
raise HTTPException(status_code=404, detail="Item not found")
# Critical authorization check: ensure the item belongs to the requesting user
if item["owner"] != current_user:
raise HTTPException(
status_code=403,
detail="You do not have access to this item",
)
return {"item_id": item_id, "data": item["data"]}
This pattern ensures that after Basic Auth validates identity, each route verifies that the authenticated user owns the requested resource. For UUID-based references, compare the requesting user’s ID or tenant ID against the object’s metadata rather than trusting the reference alone.
Additional remediation practices include:
- Always pair path parameters with server-side ownership or role checks; never rely on client-supplied flags (e.g., is_owner) that can be tampered with.
- Use opaque identifiers (e.g., UUIDs) instead of sequential integers to reduce the risk of automated enumeration, though this must be paired with authorization checks.
- Leverage FastAPI dependencies to centralize authorization logic, making it easier to audit and maintain consistent rules across endpoints.
- Ensure responses do not leak information about the existence of other objects (use generic not-found messages) to reduce user enumeration via timing differences.
middleBrick’s scans for BOLA/IDOR include runtime tests that attempt cross-user access and inspect OpenAPI specs to confirm that security schemes are defined and applied. By combining these scans with the code patterns above, you can reduce the likelihood of IDOR findings in reports generated via the CLI (middlebrick scan <url>), Dashboard, or GitHub Action integrations that fail builds when risk thresholds are exceeded.
Related CWEs: bolaAuthorization
| CWE ID | Name | Severity |
|---|---|---|
| CWE-250 | Execution with Unnecessary Privileges | HIGH |
| CWE-639 | Insecure Direct Object Reference | CRITICAL |
| CWE-732 | Incorrect Permission Assignment | HIGH |