How PasswordAuthMiddleware Secures API Endpoints in Open Notebook
PasswordAuthMiddleware is a FastAPI middleware that intercepts every incoming request to verify a Bearer token against the OPEN_NOTEBOOK_PASSWORD environment variable, returning 401 Unauthorized for missing or invalid credentials while allowing configured public paths to bypass authentication.
The open-notebook project implements a lightweight authentication layer using Starlette-based middleware to protect its REST API surface. Located in api/auth.py, the PasswordAuthMiddleware class provides a single-password gate that validates HTTP requests before they reach your route handlers, making it ideal for self-hosted deployments where simplicity outweighs complex user management.
How PasswordAuthMiddleware Works
The middleware implements a seven-step protection strategy that processes every request before it reaches the application routers.
Password Source and Initialization
At startup, the middleware initializes by reading the secret OPEN_NOTEBOOK_PASSWORD environment variable (or Docker secret file) via the get_secret_from_env helper in open_notebook/utils/encryption.py. If this variable is missing, the middleware becomes a no-op, allowing the API to run without authentication. This design supports local development environments where password protection is unnecessary.
Path-Based Exclusions
The middleware accepts an excluded_paths parameter during registration in api/main.py. Requests matching any path in this list bypass the password check entirely. Common exclusions include root paths, health checks, and API documentation endpoints.
# api/main.py – middleware registration with excluded paths
app.add_middleware(
PasswordAuthMiddleware,
excluded_paths=[
"/", "/health", "/docs", "/openapi.json", "/redoc",
"/api/auth/status", "/api/config",
],
)
CORS Pre-flight Handling
OPTIONS requests for CORS pre-flight checks are automatically allowed without authentication. This prevents browsers from blocking legitimate cross-origin requests before the actual API call occurs.
Header Validation and Authentication Flow
For all non-excluded requests, the middleware enforces a strict validation sequence:
-
Presence Check: If the
Authorizationheader is missing, the middleware returns 401 Unauthorized with aWWW-Authenticate: Bearerheader to prompt credential submission. -
Format Validation: The header must conform to the pattern
Bearer {password}. Malformed headers return 401 with the message "Invalid authorization header format". -
Password Verification: The extracted token is compared to the stored password. A mismatch yields 401 with "Invalid password".
-
Request Forwarding: When validation succeeds, the middleware hands the request to the downstream handler via
call_nextand returns the response unchanged.
Route-Level Protection with check_api_password
Beyond global middleware, the api/auth.py module exports check_api_password, a FastAPI dependency that individual routes can use to enforce authentication without applying the middleware to the entire application. This is useful for securing specific admin endpoints while keeping the rest of the API public.
from api.auth import check_api_password
@router.get("/admin")
async def admin_panel(valid: bool = Depends(check_api_password)):
return {"msg": "You are authorized"}
Client Authentication Examples
When calling protected endpoints, clients must include the password in the Authorization header using the Bearer scheme.
curl -H "Authorization: Bearer my-secret-pw" \
http://localhost:5055/api/notebooks
If authentication fails, the server responds with a 401 status code and a JSON detail message:
{
"detail": "Invalid password"
}
Missing headers trigger a 401 response with the WWW-Authenticate: Bearer challenge header, prompting clients to resubmit with credentials.
Summary
- PasswordAuthMiddleware intercepts all HTTP requests in
api/auth.pybefore they reach FastAPI routers. - It reads the
OPEN_NOTEBOOK_PASSWORDfrom environment variables viaget_secret_from_env, becoming a no-op if unset. - The excluded_paths parameter in
api/main.pyallows public access to health checks, documentation, and configuration endpoints. - OPTIONS requests bypass authentication to support CORS pre-flight checks.
- Invalid or missing Bearer tokens return 401 Unauthorized with specific error messages.
- The check_api_password dependency enables per-route authentication without global middleware.
Frequently Asked Questions
What happens if OPEN_NOTEBOOK_PASSWORD is not set?
When the OPEN_NOTEBOOK_PASSWORD environment variable is missing, the middleware initializes in a no-op state. All requests pass through without authentication, allowing the API to run in unsecured mode—typically used for local development environments.
How do I exclude specific endpoints from authentication?
Pass a list of paths to the excluded_paths parameter when adding the middleware in api/main.py. Any request whose path matches an entry in this list bypasses the password check entirely. Common exclusions include /health, /docs, /openapi.json, and /redoc.
Can I use PasswordAuthMiddleware for individual routes only?
Yes. Instead of applying the middleware globally, import the check_api_password dependency from api/auth.py and add it to specific route handlers using FastAPI's Depends mechanism. This approach secures only selected endpoints while leaving others publicly accessible.
What is the correct format for the Authorization header?
The middleware expects the header in the format Authorization: Bearer {password} where {password} matches the value stored in OPEN_NOTEBOOK_PASSWORD. Requests missing the "Bearer" prefix or containing malformed tokens receive a 401 response with "Invalid authorization header format".
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →