How to Secure the Open Notebook FastAPI Application with PasswordAuthMiddleware in Production

Deploy Open Notebook in production by enabling PasswordAuthMiddleware with a strong OPEN_NOTEBOOK_PASSWORD, registering it early in the FastAPI application stack, and restricting CORS to your trusted frontend domains.

Open Notebook (lfnovo/open-notebook) ships with a built-in authentication layer for its FastAPI backend. The PasswordAuthMiddleware—implemented in api/auth.py (lines 12–115)—provides password-based protection for all API endpoints, making it ideal for securing personal or small-team deployments without external identity providers.

Set the Authentication Secret

The middleware reads the password using get_secret_from_env from open_notebook/utils/encryption.py, which supports both plain environment variables and Docker secrets.

Environment Variable Configuration

Set a cryptographically strong password in your environment before starting the application:

export OPEN_NOTEBOOK_PASSWORD="your-very-long-random-secret-here"

Docker Secrets Support

For containerized deployments, store the password in a secret file and reference it via the OPEN_NOTEBOOK_PASSWORD_FILE variable:

export OPEN_NOTEBOOK_PASSWORD_FILE=/run/secrets/api_password

The helper function automatically detects the _FILE suffix and reads the secret from disk, falling back to the plain variable if the file is not present.

Register PasswordAuthMiddleware in the FastAPI Stack

Add the middleware early in your application initialization so it executes before any router logic. In api/main.py (lines 73–86), the registration looks like this:

from api.auth import PasswordAuthMiddleware

app.add_middleware(
    PasswordAuthMiddleware,
    excluded_paths=[
        "/", "/health", "/docs", "/openapi.json", "/redoc",
        "/api/auth/status", "/api/config",
    ],
)

The excluded_paths parameter (configured in lines 77–85) ensures that health checks, OpenAPI documentation, and the authentication status endpoint remain publicly accessible. All other routes—including notebook and chat endpoints—require the Bearer token.

Lock Down Production Infrastructure

Enabling the middleware is only the first step. You must also harden the transport layer and access controls.

Enforce TLS Termination

The middleware validates the Authorization: Bearer <password> header, but it does not encrypt traffic. Always run the API behind a reverse proxy such as Nginx or Traefik with TLS termination configured. This prevents the password from being intercepted in transit.

Restrict CORS Origins

By default, the application allows all origins (*), which is insecure for production. Set the CORS_ORIGINS environment variable to your exact frontend URL:

export CORS_ORIGINS="https://notebook.example.com"

The _parse_cors_origins helper in api/main.py (lines 53–59) parses this string and configures FastAPI's CORSMiddleware accordingly.

Audit Failed Authentication Attempts

When authentication fails, the middleware returns a 401 Unauthorized response with a WWW-Authenticate: Bearer header. Configure your reverse proxy or logging infrastructure to capture these 401 responses for security monitoring.

Verify End-to-End Protection

Test the configuration using curl to ensure the middleware blocks unauthorized requests while allowing valid ones.

Check the public status endpoint—implemented in api/routers/auth.py (lines 12–27)—which requires no authentication:

curl http://localhost:5055/api/auth/status

Attempt to access a protected endpoint without credentials:

curl http://localhost:5055/api/notes

# Expected: 401 Unauthorized

Access the same endpoint with the correct Bearer token:

curl -H "Authorization: Bearer $OPEN_NOTEBOOK_PASSWORD" \
  http://localhost:5055/api/notes

Summary

  • Configure the secret using OPEN_NOTEBOOK_PASSWORD or OPEN_NOTEBOOK_PASSWORD_FILE via get_secret_from_env in open_notebook/utils/encryption.py.
  • Register the middleware in api/main.py with app.add_middleware(PasswordAuthMiddleware, ...) and verify your excluded_paths list.
  • Exclude public endpoints such as /health, /docs, and /api/auth/status to allow monitoring and documentation access.
  • Run behind TLS to protect the Bearer token in transit.
  • Restrict CORS by setting CORS_ORIGINS to specific domains rather than the default wildcard.

Frequently Asked Questions

What endpoints are excluded from authentication by default?

The default excluded_paths list in api/main.py includes the root path (/), health check (/health), OpenAPI documentation (/docs, /openapi.json, /redoc), and the authentication status endpoint (/api/auth/status). These remain accessible without a password so that load balancers can perform health checks and developers can inspect the API schema.

Can I use a file-based secret instead of an environment variable?

Yes. The get_secret_from_env utility supports Docker secrets via the OPEN_NOTEBOOK_PASSWORD_FILE environment variable. If this variable is set and points to a readable file, the middleware reads the password from that file. Otherwise, it falls back to the value of OPEN_NOTEBOOK_PASSWORD.

How does the middleware handle missing or incorrect passwords?

When a request lacks the Authorization header or contains an incorrect Bearer token, PasswordAuthMiddleware (defined in api/auth.py) immediately returns a 401 Unauthorized response with a WWW-Authenticate: Bearer header. The response body contains a JSON error message, and the request is not forwarded to any downstream routers.

Is the PasswordAuthMiddleware sufficient for high-security environments?

While PasswordAuthMiddleware provides basic access control suitable for personal deployments, high-security environments should combine it with network-level firewalls, VPNs, or integrate with OAuth2/OpenID Connect providers. The middleware performs no rate limiting or account lockout, so pair it with a reverse proxy that can handle brute-force protection and IP whitelisting.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →