PasswordAuthMiddleware Authentication Flow in Open Notebook: Implementation Guide
Open Notebook's PasswordAuthMiddleware implements a simple Bearer token authentication system that validates Authorization headers against environment-configured passwords while automatically exempting health checks and documentation endpoints from security checks.
Open Notebook secures its FastAPI API using a lightweight password-based middleware defined in api/auth.py. The PasswordAuthMiddleware class provides a transparent security layer that requires no external identity providers, making it ideal for single-user deployments or development environments where simple access control is sufficient.
Password Loading and Configuration
Environment-Based Secret Retrieval
The middleware initializes by loading the authentication secret from environment variables. It uses the get_secret_from_env helper function to check OPEN_NOTEBOOK_PASSWORD directly, or reads from a Docker secret file specified by OPEN_NOTEBOOK_PASSWORD_FILE in api/auth.py.
If neither environment variable is configured, the middleware disables authentication entirely and allows all requests to pass through without validation. This design provides a seamless toggle for development environments without code changes.
Request Filtering and Public Path Exclusions
Whitelisted Endpoints and CORS Handling
PasswordAuthMiddleware automatically bypasses authentication for specific public paths defined in the source code. These exempt routes include the root endpoint (/), /health, /docs, /openapi.json, and /redoc.
The middleware also skips CORS pre-flight OPTIONS requests to ensure proper cross-origin resource sharing functionality. This filtering occurs before any token validation, allowing public health checks and API documentation to remain accessible without credentials.
Bearer Token Validation Flow
Header Verification and Error Responses
For all non-excluded requests, the middleware enforces Bearer token authentication via the Authorization header. The system expects the format Authorization: Bearer <password>, where the token value must match the password loaded from environment variables.
If the header is missing, malformed, or contains an incorrect token, PasswordAuthMiddleware returns a 401 Unauthorized response with a WWW-Authenticate: Bearer challenge header. When the token matches the configured password, the request proceeds to the next handler in the FastAPI pipeline.
Frontend Authentication Integration
Checking Authentication Status
The frontend determines whether to prompt for credentials by querying the /api/auth/status endpoint defined in api/routers/auth.py. This endpoint reports whether OPEN_NOTEBOOK_PASSWORD is configured, allowing the UI to adapt dynamically to the server's security settings.
// src/lib/stores/auth-store.ts – checkAuthRequired()
const response = await fetch(`${apiUrl}/api/auth/status`, {
cache: 'no-store',
});
const data = await response.json();
const authEnabled = data.auth_enabled;
Client Login Implementation
When authentication is enabled, the frontend submits the user-provided password as a Bearer token in the Authorization header. The store validates credentials by attempting to access a protected endpoint, storing the token only upon successful response.
// src/lib/stores/auth-store.ts – login()
const response = await fetch(`${apiUrl}/api/notebooks`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${password}`,
'Content-Type': 'application/json',
},
});
if (response.ok) {
// Save token, mark user as authenticated
}
Server-Side Middleware Setup
The middleware is attached to the FastAPI application in api/main.py using the standard middleware pattern. While you can specify additional excluded paths during initialization, the middleware already handles common public routes internally.
# api/main.py (excerpt)
from open_notebook.auth import PasswordAuthMiddleware
app.add_middleware(PasswordAuthMiddleware, excluded_paths=["/health"])
When a protected endpoint like GET /api/notebooks receives a request, the middleware intercepts the call, validates the Bearer token, and either rejects the request with a 401 status or passes the request to the route handler.
Summary
- PasswordAuthMiddleware loads secrets from
OPEN_NOTEBOOK_PASSWORDorOPEN_NOTEBOOK_PASSWORD_FILEusingget_secret_from_env - Public paths including
/health,/docs, and/redocbypass authentication automatically along withOPTIONSrequests - Protected endpoints require valid
Authorization: Bearer <password>headers for access - The frontend checks authentication requirements via
/api/auth/statusbefore prompting for credentials - Invalid or missing tokens trigger
401 Unauthorizedresponses withWWW-Authenticate: Bearerchallenge headers
Frequently Asked Questions
What happens if OPEN_NOTEBOOK_PASSWORD is not set?
If neither OPEN_NOTEBOOK_PASSWORD nor OPEN_NOTEBOOK_PASSWORD_FILE is configured, PasswordAuthMiddleware disables authentication entirely and allows all requests to pass through without token validation, effectively running the API in open mode.
Which endpoints are excluded from PasswordAuthMiddleware checks?
The middleware automatically exempts the root path (/), /health, /docs, /openapi.json, /redoc, and all CORS pre-flight OPTIONS requests from authentication requirements, ensuring health checks and API documentation remain publicly accessible.
How does the frontend know if authentication is required?
The frontend queries the /api/auth/status endpoint to check if a password is configured on the server. This endpoint returns a boolean auth_enabled property that determines whether the UI should present a login prompt to the user.
What response does PasswordAuthMiddleware return for invalid tokens?
For requests with missing, malformed, or incorrect Bearer tokens, the middleware returns a 401 Unauthorized HTTP status code and includes a WWW-Authenticate: Bearer response header to challenge the client for valid credentials according to RFC 6750 standards.
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 →