# Porchlight OpenID Connect Provider with user management, built with FastAPI. Porchlight handles user registration (via magic links), credential management (passwords and WebAuthn security keys), and issues OIDC tokens for relying parties. It uses SQLite for storage, Jinja2 + HTMX for the UI, and idpyoidc for the OIDC protocol layer. ## Production Setup ### Docker (recommended) ```bash docker compose --profile prod up --build ``` This starts Porchlight on port 8000 with 4 uvicorn workers. Data is persisted in a named Docker volume. Set required environment variables in `docker-compose.yml` or via `.env`: ```bash OIDC_OP_ISSUER=https://auth.example.com OIDC_OP_SESSION_SECRET= ``` ### Manual Requires Python 3.13+ and [uv](https://docs.astral.sh/uv/). ```bash uv sync --no-dev OIDC_OP_ISSUER=https://auth.example.com \ OIDC_OP_SESSION_SECRET=$(python -c "import secrets; print(secrets.token_hex(32))") \ uv run uvicorn fastapi_oidc_op.app:create_app \ --factory --host 0.0.0.0 --port 8000 --workers 4 ``` ### Configuration All settings are read from environment variables with the `OIDC_OP_` prefix: | Variable | Default | Description | |---|---|---| | `OIDC_OP_ISSUER` | **required** | OIDC issuer URL (must match public URL) | | `OIDC_OP_SESSION_SECRET` | random per process | Session cookie signing secret | | `OIDC_OP_DEBUG` | `false` | Enable `/docs` Swagger UI | | `OIDC_OP_SQLITE_PATH` | `data/oidc_op.db` | SQLite database path | | `OIDC_OP_SIGNING_KEY_PATH` | `data/keys` | OIDC signing key storage | | `OIDC_OP_INVITE_TTL` | `86400` | Magic link expiry in seconds | | `OIDC_OP_MANAGE_CLIENT_ID` | `manage-app` | Client ID for the management UI | Database migrations run automatically on startup. ## Development Setup ### Prerequisites - Python 3.13+ - [uv](https://docs.astral.sh/uv/) - Node.js (for e2e tests) ### Getting started ```bash # Install dependencies (including dev tools) uv sync # Start the dev server with hot reload OIDC_OP_ISSUER=http://localhost:8000 OIDC_OP_DEBUG=true \ uv run uvicorn fastapi_oidc_op.app:create_app \ --factory --host 127.0.0.1 --port 8000 --reload --reload-dir src ``` Or with Docker: ```bash docker compose --profile dev up --build ``` ### Running tests ```bash # Unit/integration tests uv run pytest # Lint and format uv run ruff check src/ tests/ --fix uv run ruff format src/ tests/ # Type checking uv run ty check src/ ``` ### End-to-end browser tests The e2e suite uses Playwright (Node.js) to test all user-facing flows against a running instance of the app. ```bash # One-time setup: install Playwright and Chromium cd tests/e2e npm install && npm run setup cd ../.. # Run all e2e tests ./tests/e2e/run.sh # Run a specific test ./tests/e2e/run.sh tests/e2e/test_login.js # Run with visible browser (not headless) E2E_HEADLESS=0 ./tests/e2e/run.sh ``` The runner starts the app on port 8099, seeds test fixtures into a temporary SQLite database, runs all `test_*.js` files, and tears everything down. ### Full quality check ```bash uv run ruff format src/ tests/ uv run ruff check src/ tests/ --fix uv run ty check src/ uv run pytest ./tests/e2e/run.sh ```