MEDIUM clickjackingfastapibasic auth

Clickjacking in Fastapi with Basic Auth

Clickjacking in Fastapi with Basic Auth — how this specific combination creates or exposes the vulnerability

Clickjacking is a client-side UI redress attack where an attacker tricks a user into interacting with a transparent or opaque element embedded over a legitimate page. In a Fastapi application that uses HTTP Basic Authentication, combining browser-based login flows with pages that do not enforce frame isolation can expose authentication actions to clickjacking. When Basic Auth is handled by the browser (rather than a custom login form), the browser’s built-in credentials dialog is not vulnerable to DOM overlay attacks; however, if the application renders pages that can be framed, an attacker can overlay invisible frames or buttons on top of legitimate UI elements (such as “Confirm” or “Revoke” actions) and capture user interactions, including initiating authenticated flows that trigger the browser’s Basic Auth prompt.

Consider a Fastapi endpoint that conditionally prompts for Basic Auth by returning a 401 with WWW-Authenticate: Basic. If the same endpoint serves HTML that is embeddable in an <iframe> (missing X-Frame-Options or Content-Security-Policy: frame-ancestors), an attacker can embed the endpoint in a malicious page. When the victim visits the attacker’s site, the browser may show the native credentials dialog if no cached credentials exist. Even if credentials are cached and the request proceeds inside the invisible frame, the attacker can drive UI interactions (e.g., form submissions or API calls initiated from the embedded origin) that occur within the authenticated session opened inside the frame. Because the attacker controls the framing context, they can induce the victim to perform actions while the browser attaches the Basic Auth credentials automatically, leading to unauthorized operations like changing settings or making requests on behalf of the user.

middleBrick detects this risk by running the 12 parallel security checks, including Input Validation and Security Headers. For an endpoint served by Fastapi that lacks frame-ancestors restrictions or relies on browser-managed authentication in an embeddable context, the scan reports a finding with severity Medium and references the OWASP UI Redress category. The scan does not assume an authenticated session; it observes whether the response permits framing and whether authentication is browser-driven in a way that can be abused via clickjacking vectors. Remediation focuses on preventing the page from being embedded and ensuring that sensitive actions require explicit user consent outside of easily frameable contexts.

Basic Auth-Specific Remediation in Fastapi — concrete code fixes

To mitigate clickjacking in a Fastapi application using HTTP Basic Authentication, you must enforce strict frame control and avoid relying on the browser’s default authentication dialog inside frames. The primary defenses are security headers and careful handling of authentication flows.

Security headers in Fastapi

Set X-Frame-Options to DENY or SAMEORIGIN and use Content-Security-Policy with a restrictive frame-ancestors directive. These headers prevent the browser from rendering the page inside an iframe unless explicitly allowed.

from fastapi import Fastapi, Request
from fastapi.responses import HTMLResponse

app = Fastapi()

@app.middleware("http")
async def add_security_headers(request: Request, call_next):
    response = call_next(request)
    if not response.headers.get("X-Frame-Options"):
        response.headers["X-Frame-Options"] = "DENY"
    if not response.headers.get("Content-Security-Policy"):
        response.headers["Content-Security-Policy"] = "frame-ancestors 'none'"
    return response

This ensures that pages requiring authentication cannot be embedded, reducing the attack surface for clickjacking when using browser-managed Basic Auth.

Explicit authentication flow

Instead of relying on the browser’s Basic Auth dialog inside frames, implement a form-based login that sets a session cookie after verifying credentials. This moves authentication out of the browser’s native prompt and allows you to enforce frame busting and CSRF protection. Below is an example using Fastapi with password hashing and session cookies, avoiding reliance on WWW-Authenticate for sensitive actions.

from fastapi import Fastapi, Depends, HTTPException, status, Response
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from starlette.responses import HTMLResponse
import secrets

app = Fastapi()
security = HTTPBasic()

# In-memory store for demo; use a proper session store in production
sessions = {}

def verify_user(credentials: HTTPBasicCredentials):
    # Replace with secure user verification, e.g., database lookup with hashed passwords
    if credentials.username == "alice" and credentials.password == "secret":
        token = secrets.token_urlsafe(16)
        sessions[token] = credentials.username
        return token
    return None

@app.post("/login")
async def login(response: Response, credentials: HTTPBasicCredentials = security.credentials(request=None)):
    token = verify_user(credentials)
    if token is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid credentials",
            headers={"WWW-Authenticate": "Basic"},
        )
    response.set_cookie("session_token", token, httponly=True, samesite="strict", secure=True)
    return {"message": "Logged in"}

@app.get("/protected")
async def protected(token: str = Cookie(None)):
    if token is None or sessions.get(token) != "alice":
        raise HTTPException(status_code=401, detail="Unauthorized")
    return {"data": "protected"}

By using cookie-based sessions with SameSite=Strict and HttpOnly, you avoid exposing credentials to clickjacking via framed contexts. If you must support Basic Auth for compatibility, ensure that sensitive endpoints reject requests that arrive via an embedded frame by checking Referer or using a one-time token (nonce) to prevent forged requests initiated through clickjacking.

Frequently Asked Questions

Does middleBrick test clickjacking when Basic Auth is used?
Yes. middleBrick includes Security Headers checks (X-Frame-Options and Content-Security-Policy frame-ancestors) in its parallel scan, which surfaces whether pages that trigger browser-managed Basic Auth are embeddable and therefore exposed to clickjacking.
Can I rely on browser Basic Auth dialogs inside iframes if I set CSP frame-ancestors?
Setting a strict CSP frame-ancestors policy prevents embedding and reduces clickjacking risk. However, browser-managed Basic Auth dialogs are not DOM-accessible, so the main risk shifts to ensuring that sensitive workflows are not initiated via invisible frames; prefer form-based authentication with CSRF protection for high-sensitivity actions.