# Configure Password Authentication Middleware for Production in Open Notebook

> Secure your Open Notebook production environment by configuring password authentication middleware. Learn how to set environment variables or Docker secrets for robust API security.

- Repository: [Luis Novo/open-notebook](https://github.com/lfnovo/open-notebook)
- Tags: how-to-guide
- Published: 2026-07-05

---

**Enable production security by setting the `OPEN_NOTEBOOK_PASSWORD` environment variable or Docker secret, ensuring every API request includes a valid `Authorization: Bearer <password>` header.**

Open Notebook secures its HTTP API with a lightweight `PasswordAuthMiddleware` that validates bearer tokens on every request. In development environments, the middleware automatically falls back to "no password" when `OPEN_NOTEBOOK_PASSWORD` is unset, but production deployments require explicit configuration to prevent unauthorized access. This guide covers the exact implementation details sourced from `lfnovo/open-notebook` to help you configure robust password authentication for production workloads.

## How Password Authentication Works

The `PasswordAuthMiddleware` class defined in [`api/auth.py`](https://github.com/lfnovo/open-notebook/blob/main/api/auth.py) intercepts incoming requests and validates the `Authorization` header against a configured secret. When a request arrives, the middleware checks if the path is in the exclusion list (health checks, OpenAPI documentation, and internal status routes) or if the bearer token matches the expected password.

In [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) (lines 73–86), the middleware is instantiated before the CORS middleware. This ordering ensures that unauthenticated requests are rejected before any CORS handling occurs, preventing unauthorized access from reaching your business logic. The middleware supports two secret sources: a plain environment variable (`OPEN_NOTEBOOK_PASSWORD`) or a file-based Docker secret (`OPEN_NOTEBOOK_PASSWORD_FILE`), with the latter taking precedence when both are present.

## Production Configuration Steps

### Generate a Strong Password

Create a cryptographically secure password using your system's entropy source. The password should be at least 32 characters long and contain a mix of alphanumeric and special characters to prevent brute-force attacks.

### Configure Environment Variables or Docker Secrets

The `get_secret_from_env` function in [`open_notebook/utils/encryption.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py) (lines 29–59) handles secret retrieval by first checking for a `<VAR>_FILE` pattern, then falling back to the plain environment variable. This design supports both Docker Swarm/Kubernetes secret mounts and traditional `.env` files.

For Docker-based deployments, use the secret file approach:

```yaml
services:
  api:
    image: lfnovo/open-notebook:latest
    env_file: .env.production
    secrets:
      - open_notebook_password
    ports:
      - "5055:5055"

secrets:
  open_notebook_password:
    file: ./secrets/open_notebook_password.txt

```

Your `.env.production` file should reference the secret file or contain the plain variable:

```dotenv

# Option 1: File-based secret (recommended for Docker)

# The _FILE suffix is automatically detected by get_secret_from_env

# Option 2: Plain environment variable

# OPEN_NOTEBOOK_PASSWORD=SuperSecretProdPass123!

CORS_ORIGINS=https://notebook.example.com

```

### Restart the API Service

The password is read at process startup in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py). After changing the secret, restart the container to ensure the middleware picks up the new value. Running processes do not reload the password dynamically.

### Update Client Authorization Headers

The built-in client library in [`api/client.py`](https://github.com/lfnovo/open-notebook/blob/main/api/client.py) automatically reads `OPEN_NOTEBOOK_PASSWORD` from the environment and adds the `Authorization: Bearer <password>` header to all requests. When using custom HTTP clients, implement the header manually:

```python
import os
from open_notebook.api.client import OpenNotebookClient

# Ensure the environment variable is set

os.environ["OPEN_NOTEBOOK_PASSWORD"] = "SuperSecretProdPass123!"

client = OpenNotebookClient(base_url="https://api.example.com")

# All subsequent API calls include the Authorization header automatically

```

## Implementation Details and Source Files

### Middleware Registration in api/main.py

The middleware is registered with specific excluded paths for public endpoints:

```python

# From api/main.py (lines 73-86)

app.add_middleware(
    PasswordAuthMiddleware,
    exclude_paths=["/health", "/docs", "/openapi.json", "/redoc"]
)

```

### Secret Retrieval Logic

The `get_secret_from_env` utility in [`open_notebook/utils/encryption.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py) handles both file-based and environment-based secrets:

```python

# Conceptual implementation from open_notebook/utils/encryption.py

def get_secret_from_env(var_name: str) -> str:
    file_var = f"{var_name}_FILE"
    if file_var in os.environ:
        with open(os.environ[file_var], 'r') as f:
            return f.read().strip()
    return os.environ.get(var_name, "")

```

### Optional Dependency for Fine-Grained Control

For specific routes requiring explicit authentication checks, use the `check_api_password` dependency:

```python
from fastapi import APIRouter, Depends, HTTPException
from api.auth import check_api_password

router = APIRouter()

@router.get("/admin/status")
async def admin_status(auth_ok: bool = Depends(check_api_password)):
    if not auth_ok:
        raise HTTPException(status_code=401, detail="Unauthorized")
    return {"msg": "All systems nominal"}

```

## Verifying Your Production Configuration

After restarting the API, test authentication using curl:

```bash

# This should return 401 Unauthorized

curl https://api.example.com/notes

# This should succeed with proper authorization

curl -H "Authorization: Bearer SuperSecretProdPass123!" https://api.example.com/notes

```

Public endpoints like `/health` and `/docs` should remain accessible without headers, while all business logic routes require the bearer token.

## Summary

- **Configure** the `OPEN_NOTEBOOK_PASSWORD` environment variable or `OPEN_NOTEBOOK_PASSWORD_FILE` Docker secret to enable production authentication.
- **Restart** the API process after setting secrets, as the middleware reads passwords only at startup.
- **Verify** that excluded paths (health checks, documentation) remain public while all other routes require `Authorization: Bearer <password>` headers.
- **Use** the built-in `OpenNotebookClient` from [`api/client.py`](https://github.com/lfnovo/open-notebook/blob/main/api/client.py) to automatically handle header injection, or manually implement the bearer token pattern in custom clients.
- **Reference** [`api/auth.py`](https://github.com/lfnovo/open-notebook/blob/main/api/auth.py), [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py), and [`open_notebook/utils/encryption.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py) for the underlying implementation details.

## Frequently Asked Questions

### What happens if OPEN_NOTEBOOK_PASSWORD is not set in production?

According to the source code in [`open_notebook/utils/encryption.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py), the middleware falls back to an empty string when both `OPEN_NOTEBOOK_PASSWORD` and `OPEN_NOTEBOOK_PASSWORD_FILE` are unset. In this state, the authentication check passes for any request, effectively disabling password protection. This behavior is intended for development but creates a security vulnerability in production.

### Which endpoints bypass authentication by default?

The middleware initialization in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) excludes specific paths including `/health` (health checks), `/docs` (Swagger documentation), `/redoc` (alternative documentation), and [`/openapi.json`](https://github.com/lfnovo/open-notebook/blob/main//openapi.json) (schema specification). These endpoints remain publicly accessible to support monitoring tools and API exploration, while all other routes require valid bearer tokens.

### Can I configure multiple passwords or user accounts?

The current `PasswordAuthMiddleware` implementation in [`api/auth.py`](https://github.com/lfnovo/open-notebook/blob/main/api/auth.py) supports only a single global password. There is no built-in multi-user authentication or role-based access control. For multi-user deployments, you should implement an additional authorization layer or place Open Notebook behind an API gateway that handles user management and passes authenticated requests through.

### How does the client library handle authentication automatically?

The `OpenNotebookClient` class in [`api/client.py`](https://github.com/lfnovo/open-notebook/blob/main/api/client.py) reads the `OPEN_NOTEBOOK_PASSWORD` environment variable during initialization and stores it in the session headers. Every HTTP request made through this client automatically includes `Authorization: Bearer <password>`, eliminating the need to manually format headers for each API call. This ensures consistent authentication across all client interactions when the environment variable is properly configured.