Skip to main content

Lightweight LDAP/AD authentication proxy and FastAPI middleware

Project description

LDAPGate

LDAPGate

Lightweight LDAP/AD authentication gateway for Python web apps. Install it, configure it, done.

Features

  • Two deployment modes — standalone reverse proxy or drop-in FastAPI middleware
  • WebDAV + browser in one — browsers get a login form; WebDAV clients (Windows, macOS Finder, curl) get a Basic auth challenge — same endpoint, no extra config
  • Pure Python LDAP — no OS-level libs required, uses ldap3
  • Signed cookie sessions — stateless, no server-side session storage
  • OpenLDAP and Active Directoryuid= and sAMAccountName= out of the box
  • Optional group gating — restrict access to members of a specific LDAP group
  • Header injection — injects X-Forwarded-User for downstream apps
  • Bundled login form — responsive, dark/light mode, customisable, works air-gapped

Install

pip install ldapgate

Config file

Both modes share the same ldapgate.yaml:

ldap:
  url: ldaps://dc.example.com:636
  bind_dn: CN=svc,CN=Users,DC=example,DC=com
  bind_password: secret
  base_dn: DC=example,DC=com
  user_filter: "(sAMAccountName={username})"         # AD; OpenLDAP: (uid={username})
  # LDAPGate requires at least one authorization rule by default:
  group_dn: CN=app-users,CN=Users,DC=example,DC=com  # restrict by group
  allowed_users:                                      # or restrict by local allowlist
    - alice
    - bob
  timeout: 10
  tls_validate: REQUIRED                             # NONE | OPTIONAL | REQUIRED
  tls_ca_cert_file: /etc/ssl/certs/internal-ca.pem  # optional — custom CA bundle
  tls_client_cert_file: /etc/ssl/certs/client.pem   # optional — mutual TLS client cert
  tls_client_key_file: /etc/ssl/private/client.key  # optional — mutual TLS client key

proxy:
  listen_host: 0.0.0.0
  listen_port: 9000
  backend_url: http://localhost:8080
  secret_key: change-me-to-something-random
  session_ttl: 3600
  user_header: X-Forwarded-User
  login_path: /_auth/login
  logout_path: /_auth/logout
  app_name: MyApp
  secure_cookies: false                              # set true when behind HTTPS

All settings can also be provided via environment variables using __ as a separator — e.g. LDAP__URL, PROXY__SECRET_KEY.

Corporate / Active Directory setup

For corp environments with internal CAs where cert validation isn't feasible:

ldap:
  url: ldaps://dc.example.com:636
  tls_validate: NONE
  # ... other settings ...

⚠️ Warning: tls_validate: NONE disables all TLS certificate validation and makes you vulnerable to man-in-the-middle attacks. Whenever possible, use tls_ca_cert_file to trust your internal CA instead.

For plain LDAP with STARTTLS:

ldap:
  url: ldap://dc.example.com:389
  use_starttls: true

Mode 1 — Standalone Reverse Proxy

Run ldapgate as a standalone process in front of any app.

Browser / WebDAV client → ldapgate :9000 → backend app :8080
ldapgate serve --config ldapgate.yaml

All traffic is intercepted by ldapgate before reaching the backend. Authenticated requests are forwarded with the X-Forwarded-User header set to the verified username. Apps can point their logout link at the configured logout_path (default /_auth/logout) to clear the session.

WebDAV clients receive a 401 WWW-Authenticate: Basic challenge automatically and authenticate per-request via HTTP Basic auth — no session cookie needed.


Mode 2 — FastAPI Middleware

Drop ldapgate auth directly into an existing FastAPI app — no separate process.

from fastapi import FastAPI
from ldapgate.config import load_config
from ldapgate.middleware import add_ldap_auth

app = FastAPI()
config = load_config("ldapgate.yaml")
add_ldap_auth(app, config)

@app.get("/api/data")
async def data(request):
    return {"user": request.state.user}  # authenticated username

add_ldap_auth registers the login/logout routes and attaches the middleware in one call. The authenticated username is available as request.state.user and is also injected as the configured user_header into the request headers.

WebDAV with middleware

The middleware handles both browser and WebDAV clients on the same app instance:

Client Auth flow
Browser Redirected to login form → session cookie
WebDAV (Windows, macOS Finder, curl) 401 WWW-Authenticate: Basic challenge → Basic auth per-request

No extra routes or config needed — if a request arrives without a session cookie and without Accept: text/html, the middleware issues a 401 with a WWW-Authenticate: Basic header. The client sends credentials, the middleware validates against LDAP, and the request proceeds.

allowed_users and group_dn apply to both flows — a user blocked by those settings is rejected regardless of whether they authenticated via cookie or Basic auth.

Example — xwing file server with WebDAV:

from fastapi import FastAPI
from ldapgate.config import load_config
from ldapgate.middleware import add_ldap_auth
from xwing.app import create_app
from xwing.config import Settings

xwing_settings = Settings(root_dir="/srv/files", users_config="users.yaml")
app = create_app(xwing_settings)

ldap_config = load_config("ldapgate.yaml")
add_ldap_auth(app, ldap_config)

Windows users can now map http://your-server:8989/ as a network drive:

net use Z: http://your-server:8989/ /user:alice /persistent:yes

macOS Finder: Go → Connect to Server (⌘K) → http://your-server:8989/


CLI reference

ldapgate serve [OPTIONS]

  --config PATH     Path to ldapgate.yaml (reads env vars if omitted)
  --host TEXT       Override listen host
  --port INTEGER    Override listen port
  --backend TEXT    Override backend URL
  --reload          Enable auto-reload (dev only)

Development

Requires uv.

git clone https://github.com/anudeepd/ldapgate
cd ldapgate
uv sync
uv run pytest

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ldapgate-0.1.5.tar.gz (205.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ldapgate-0.1.5-py3-none-any.whl (136.1 kB view details)

Uploaded Python 3

File details

Details for the file ldapgate-0.1.5.tar.gz.

File metadata

  • Download URL: ldapgate-0.1.5.tar.gz
  • Upload date:
  • Size: 205.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.20 {"installer":{"name":"uv","version":"0.11.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ldapgate-0.1.5.tar.gz
Algorithm Hash digest
SHA256 3353dd99770b7db925da6411fefc4f6643109e95768424cb86f7ab5c6127472c
MD5 a17031143bd7a351f62461afd7a2ce5d
BLAKE2b-256 2e1f6f308475e450d054e95c4a4e138dd2917900f2af9ecace741266d70add5b

See more details on using hashes here.

File details

Details for the file ldapgate-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: ldapgate-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 136.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.20 {"installer":{"name":"uv","version":"0.11.20","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for ldapgate-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 7a013735994d83ef73c3e29b63221b47a4029b080a18dd678c4965e6378aeacb
MD5 e50cb65702097883dfe6ae90112c890a
BLAKE2b-256 639e555f6ded93ad8b9c9a41dcde5b2d99ef12a739e1a8f04c4d87bc5f5c89c7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page