How Password Authentication Works in the Open Notebook FastAPI Backend
The Open Notebook API implements password authentication through a PasswordAuthMiddleware class that validates Bearer tokens against environment variables or Docker secrets, while supporting both global middleware protection and route-specific dependency-based checks.
The lfnovo/open-notebook repository provides a lightweight FastAPI backend for managing notebooks with a simple yet effective security model. Understanding how password authentication is implemented in the FastAPI backend reveals a flexible, middleware-based approach that supports both global protection and route-specific exemptions while allowing complete deactivation for local development.
Loading Credentials from Environment Secrets
The authentication system reads the password from the environment using the get_secret_from_env helper function defined in open_notebook/utils/encryption.py (lines 29-38). This utility supports both direct environment variables and Docker secret files.
When the application starts, it looks for OPEN_NOTEBOOK_PASSWORD in the environment. Alternatively, you can specify OPEN_NOTEBOOK_PASSWORD_FILE to point to a Docker secret file containing the credentials.
# Direct environment variable
export OPEN_NOTEBOOK_PASSWORD="my-secret-password"
# Docker secret file approach
echo "my-secret-password" > /run/secrets/open_notebook_password
export OPEN_NOTEBOOK_PASSWORD_FILE="/run/secrets/open_notebook_password"
The PasswordAuthMiddleware Implementation
The core authentication logic resides in api/auth.py within the PasswordAuthMiddleware class, which inherits from BaseHTTPMiddleware. This middleware intercepts every incoming request to enforce authentication unless explicitly configured otherwise.
Request Filtering and Exclusions
The middleware implements intelligent request filtering at lines 19-28 of api/auth.py. It automatically skips authentication when no password is configured, allowing the application to run without protection in local development scenarios.
Additionally, the middleware maintains a list of excluded paths that bypass authentication entirely:
- Root path (
/) - Health check endpoints
- API documentation (
/docs) - OpenAPI specification (
/openapi.json) - CORS pre-flight
OPTIONSrequests
Bearer Token Validation
For protected routes, the middleware extracts the Authorization header and expects the format Bearer <password>. If the header is missing, malformed, or contains an incorrect password, the middleware returns a 401 Unauthorized response with a WWW-Authenticate: Bearer header (lines 44-71 of api/auth.py).
# Making an authenticated request
curl -H "Authorization: Bearer my-secret-password" \
http://localhost:5055/api/notebooks
When authentication fails, the API returns JSON error details:
{
"detail": "Invalid password"
}
Dependency-Based Route Protection
For routes that require authentication logic outside the global middleware, the check_api_password function (lines 82-110 of api/auth.py) provides a FastAPI dependency alternative. This function performs the same validation checks as the middleware but raises HTTPException(401) for failed authentication, integrating with FastAPI's native exception handling.
from fastapi import APIRouter, Depends
from api.auth import check_api_password, security
router = APIRouter()
@router.get("/sensitive-data")
async def get_sensitive_data(auth: bool = Depends(check_api_password)):
# Authentication already validated by dependency
return {"status": "authenticated"}
Middleware Registration and Integration
The middleware is attached to the FastAPI application in api/main.py (lines 73-86). Critically, it is registered before the CORS middleware to ensure authentication runs first. The registration extends the default excluded paths to include the public auth status endpoint (/api/auth/status) and the configuration endpoint (/api/config).
app.add_middleware(
PasswordAuthMiddleware,
excluded_paths=["/api/auth/status", "/api/config"]
)
Error Handling with CORS Support
When the middleware returns a 401 response directly, the global exception handlers in api/main.py (lines 99-115) ensure that CORS headers are still added to the response. This prevents cross-origin errors in browser-based clients even when authentication fails.
Summary
- Password credentials are loaded via
get_secret_from_envfromopen_notebook/utils/encryption.py, supporting both environment variables and Docker secrets viaOPEN_NOTEBOOK_PASSWORDorOPEN_NOTEBOOK_PASSWORD_FILE. - The
PasswordAuthMiddlewareinapi/auth.pyprovides global protection using Bearer token validation, with configurable path exclusions for root, health, docs, and OpenAPI endpoints. - Route-level protection is available through the
check_api_passworddependency function for granular security control without global middleware. - The middleware is registered before CORS handling in
api/main.pyto ensure proper request interception order. - Authentication failures return
401 Unauthorizedresponses withWWW-Authenticate: Bearerheaders while maintaining CORS compatibility through global exception handlers.
Frequently Asked Questions
How do I disable password authentication in Open Notebook?
Leave the OPEN_NOTEBOOK_PASSWORD environment variable unset. The PasswordAuthMiddleware automatically skips authentication when no password is configured, making this suitable for local development environments.
What authentication header format does the Open Notebook API expect?
The API expects an Authorization header with the format Bearer <password>. For example: Authorization: Bearer my-secret-password. The middleware extracts and validates this against the configured environment secret configured via get_secret_from_env.
Can I exclude specific routes from password authentication?
Yes. When registering the middleware in api/main.py, extend the excluded_paths list to include your public endpoints. The default exclusions cover /api/auth/status and /api/config, and you can add custom paths like /public or /health to bypass authentication.
How does the middleware handle CORS pre-flight requests?
The middleware automatically allows OPTIONS requests without requiring authentication tokens. This ensures that CORS pre-flight checks from browsers succeed before the actual request is sent, preventing cross-origin errors during the handshake phase.
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 →