# How Password Authentication Works in the Open Notebook FastAPI Backend

> Discover how FastAPI password authentication works in the Open Notebook API. Learn about the PasswordAuthMiddleware, token validation, and route-specific security for your backend.

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

---

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

```bash

# 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`](https://github.com/lfnovo/open-notebook/blob/main/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`](https://github.com/lfnovo/open-notebook/blob/main/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`](https://github.com/lfnovo/open-notebook/blob/main//openapi.json))
- CORS pre-flight `OPTIONS` requests

### 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`](https://github.com/lfnovo/open-notebook/blob/main/api/auth.py)).

```bash

# 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:

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

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

```python
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`](https://github.com/lfnovo/open-notebook/blob/main/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_env` from [`open_notebook/utils/encryption.py`](https://github.com/lfnovo/open-notebook/blob/main/open_notebook/utils/encryption.py), supporting both environment variables and Docker secrets via `OPEN_NOTEBOOK_PASSWORD` or `OPEN_NOTEBOOK_PASSWORD_FILE`.
- The `PasswordAuthMiddleware` in [`api/auth.py`](https://github.com/lfnovo/open-notebook/blob/main/api/auth.py) provides 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_password` dependency function for granular security control without global middleware.
- The middleware is registered before CORS handling in [`api/main.py`](https://github.com/lfnovo/open-notebook/blob/main/api/main.py) to ensure proper request interception order.
- Authentication failures return `401 Unauthorized` responses with `WWW-Authenticate: Bearer` headers 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`](https://github.com/lfnovo/open-notebook/blob/main/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.