Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 3 additions & 45 deletions api/auth.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import secrets
from typing import Optional

from fastapi import Depends, HTTPException, Request
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from loguru import logger
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
from starlette.responses import JSONResponse, Response
from starlette.types import ASGIApp
Expand All @@ -14,7 +12,8 @@
class PasswordAuthMiddleware(BaseHTTPMiddleware):
"""
Middleware to check password authentication for all API requests.
Always active with default password if OPEN_NOTEBOOK_PASSWORD is not set.
Auth is fully disabled (no hardcoded default password) if
OPEN_NOTEBOOK_PASSWORD is not set.
Supports Docker secrets via OPEN_NOTEBOOK_PASSWORD_FILE.
"""

Expand Down Expand Up @@ -81,44 +80,3 @@ async def dispatch(
# Password is correct, proceed with the request
response = await call_next(request)
return response


# Optional: HTTPBearer security scheme for OpenAPI documentation
security = HTTPBearer(auto_error=False)


def check_api_password(
credentials: Optional[HTTPAuthorizationCredentials] = Depends(security),
) -> bool:
"""
Utility function to check API password.
Can be used as a dependency in individual routes if needed.
Supports Docker secrets via OPEN_NOTEBOOK_PASSWORD_FILE.
Returns True without checking credentials if OPEN_NOTEBOOK_PASSWORD is not configured.
Raises 401 if credentials are missing or don't match the configured password.
"""
password = get_secret_from_env("OPEN_NOTEBOOK_PASSWORD")

# No password configured - skip authentication
if not password:
return True

# No credentials provided
if not credentials:
raise HTTPException(
status_code=401,
detail="Missing authorization",
headers={"WWW-Authenticate": "Bearer"},
)

# Check password (constant-time to avoid a timing side-channel)
if not secrets.compare_digest(
credentials.credentials.encode("utf-8"), password.encode("utf-8")
):
raise HTTPException(
status_code=401,
detail="Invalid password",
headers={"WWW-Authenticate": "Bearer"},
)

return True
2 changes: 1 addition & 1 deletion docs/3-USER-GUIDE/api-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ API keys stored in the database are encrypted using Fernet (AES-128-CBC + HMAC-S

| Setting | Default Value | Production Recommendation |
|---------|---------------|---------------------------|
| Password | `open-notebook-change-me` | Set `OPEN_NOTEBOOK_PASSWORD` |
| Password | None - auth is fully disabled until set | Set `OPEN_NOTEBOOK_PASSWORD` |
| Encryption Key | None (must be set) | Set `OPEN_NOTEBOOK_ENCRYPTION_KEY` to any secret string |

**For production deployments, always set custom credentials.**
Expand Down
2 changes: 1 addition & 1 deletion docs/5-CONFIGURATION/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Any string works — it will be securely derived via SHA-256 internally. Use a s

| Setting | Default | Security Level |
|---------|---------|----------------|
| Password | `open-notebook-change-me` | Development only |
| Password | None - auth is fully disabled until `OPEN_NOTEBOOK_PASSWORD` is set | Development only |
| Encryption Key | **None** (must be configured) | Required for API key storage |

**The encryption key has no default.** You must set `OPEN_NOTEBOOK_ENCRYPTION_KEY` before using the API key configuration feature. Without it, encrypting/decrypting API keys will fail.
Expand Down
2 changes: 1 addition & 1 deletion docs/7-DEVELOPMENT/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Never pass user-provided file paths directly to file reading or content extracti

Open Notebook currently uses simple password-based middleware (`PasswordAuthMiddleware`). This is suitable for single-user self-hosted deployments but should be hardened for production:

- Change the default password (`OPEN_NOTEBOOK_PASSWORD`)
- Set `OPEN_NOTEBOOK_PASSWORD` explicitly - there is no hardcoded default password; if it's unset, auth is fully disabled (all requests pass through unchecked)
- Change the default encryption key (`OPEN_NOTEBOOK_ENCRYPTION_KEY`)
- Consider deploying behind a reverse proxy with proper authentication (OAuth, OIDC)

Expand Down
2 changes: 1 addition & 1 deletion docs/SECURITY_REVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Security review of the API key management implementation for Open Notebook. The
| Item | Status | Notes |
|------|--------|-------|
| Password protection | PASS | Bearer token authentication |
| Default password | PASS | "open-notebook-change-me" when not set |
| Default password | PASS | Auth is fully disabled (not a hardcoded default password) when `OPEN_NOTEBOOK_PASSWORD` is unset |
| Docker secrets support | PASS | `_FILE` suffix for password |
| Security warnings | PASS | Logged when using defaults |

Expand Down
Loading