Adding LDAP support

This commit is contained in:
Ian Roddis committed 2026-07-19 12:02:41 -03:00
1 parent d60ad42f0c
commit f2b99089ea
17 files changed
+541 -23

No files matched your search

+36 -13
View File
@@ -4,19 +4,19 @@ A production-shaped starting point for a web app that serves both **HTML (HTMX)*
## Stack
| Concern | Choice |
|----------------|--------|
| Web framework | FastAPI |
| HTML / interactivity | Jinja2 + HTMX |
| ORM | SQLAlchemy 2.0 (async) |
| Migrations | Alembic |
| Database | SQLite (default) or Postgres — one `DATABASE_URL` |
| Auth | JWT access + refresh tokens, rotation, DB-backed revocation |
| Authorization | RBAC: users → roles → permissions |
| Admin UI | Custom HTMX dashboard (user & role CRUD) |
| Config | env vars **or** `.env` (pydantic-settings) |
| Tooling | uv, pytest, ruff |
| Packaging | Dockerfile + docker-compose |
| Concern | Choice |
| -------------------- | ----------------------------------------------------------- |
| Web framework | FastAPI |
| HTML / interactivity | Jinja2 + HTMX |
| ORM | SQLAlchemy 2.0 (async) |
| Migrations | Alembic |
| Database | SQLite (default) or Postgres — one `DATABASE_URL` |
| Auth | JWT access + refresh tokens, rotation, DB-backed revocation |
| Authorization | RBAC: users → roles → permissions |
| Admin UI | Custom HTMX dashboard (user & role CRUD) |
| Config | env vars **or** `.env` (pydantic-settings) |
| Tooling | uv, pytest, ruff |
| Packaging | Dockerfile + docker-compose |
## Layout
@@ -154,6 +154,7 @@ Every setting is read from an environment variable first, then `.env`
| `AUTO_CREATE_TABLES` | `true` | create tables on startup (dev); use Alembic in prod |
| `COOKIE_SECURE` | `false` | set `true` behind HTTPS |
| `FIRST_SUPERUSER_EMAIL` / `_PASSWORD` | admin@example.com / changethis | used by seed |
| `LDAP_ENABLED` | `false` | validate logins against LDAP/AD (see below) |
## Auth model
@@ -168,6 +169,28 @@ stores the access token in an httpOnly cookie so pages work without client JS.
Refresh tokens are stored server-side as a SHA-256 hash + `jti` with a `revoked`
flag, so logout and rotation genuinely invalidate them.
### LDAP / Active Directory (optional)
Set `LDAP_ENABLED=true` to validate logins against a directory. On a successful
bind, a local user is **provisioned on first login** (with an unusable local
password and the roles in `LDAP_DEFAULT_ROLES`) so RBAC, tokens, and the admin
UI work unchanged. Existing accounts still authenticate against the local
database as a fallback, so the seeded superuser keeps working.
Two lookup modes (configured in `.env`, see `.env.example`):
- **Direct bind** — set `LDAP_BIND_DN_TEMPLATE`, e.g.
`uid={username},ou=people,dc=example,dc=com`; the login name is substituted
and used to bind directly.
- **Search + bind** — leave the template empty and set `LDAP_BIND_DN` /
`LDAP_BIND_PASSWORD` (a service account) plus `LDAP_USER_SEARCH_BASE` /
`LDAP_USER_SEARCH_FILTER`; the user is located, then re-bound to verify the
password.
The local user's email/name come from the `LDAP_ATTR_EMAIL` / `LDAP_ATTR_FULL_NAME`
attributes. Use `ldaps://` (`LDAP_USE_SSL=true`) or `LDAP_START_TLS=true` in
production so credentials aren't sent in cleartext.
## RBAC
`users → roles → permissions`. Permissions follow `resource:action`