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

> Secure your Open Notebook FastAPI app in production using PasswordAuthMiddleware. Add a strong password, register the middleware early, and configure CORS for trusted domains.

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

---

**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`](https://github.com/lfnovo/open-notebook/blob/main/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`](https://github.com/lfnovo/open-notebook/blob/main/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:

```bash
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:

```bash
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`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) (lines 73–86), the registration looks like this:

```python
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:

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

```

The `_parse_cors_origins` helper in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/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`](https://github.com/lfnovo/open-notebook/blob/main/api/routers/auth.py) (lines 12–27)—which requires no authentication:

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

```

Attempt to access a protected endpoint without credentials:

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

# Expected: 401 Unauthorized

```

Access the same endpoint with the correct Bearer token:

```bash
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`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py).
- **Register the middleware** in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/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`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) includes the root path (`/`), health check (`/health`), OpenAPI documentation (`/docs`, [`/openapi.json`](https://github.com/lfnovo/open-notebook/blob/main//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`](https://github.com/lfnovo/open-notebook/blob/main/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.