Dagster AuthKit v0.4.0 - Security Hardening, Cross-Pod Sessions, and We Need Your Help
TL;DR
Dagster AuthKit is a community auth/RBAC wrapper for self-hosted Dagster OSS - no fork, no code changes, just wraps dagster-webserver. v0.4.0 just shipped a big security hardening pass plus cross-pod session revocation. This post is mostly a technical breakdown of what changed and a direct ask for help: there are specific issues and PRs where I need eyes from people who actually run this stuff in production.
If you're not familiar with the project: Dagster OSS ships with zero auth. Anyone who can reach the URL has full admin access to your pipelines. AuthKit sits in front of dagster-webserver and adds login, RBAC, and audit logging without touching your repository.py or dagster.yaml.
What actually changed in v0.4.0
SECRET_KEY is now mandatory in production
Auto-generated keys were quietly rotating on every restart, which meant sessions broke silently across multi-pod deployments - you'd get random logouts with no error in the logs, just users complaining. Now the server refuses to start in production mode withoutDAGSTER_AUTH_SECRET_KEYset. Annoying if you forgot, but way better than silent breakage.python -c 'import secrets; print(secrets.token_urlsafe(32))'Proxy mode requires trusted IPs
If you run AuthKit behind Authelia/OAuth2 Proxy/Traefik, header-based auth is only as safe as your assumption that nobody can talk to the backend directly. v0.4.0 makes you either configureDAGSTER_AUTH_PROXY_TRUSTED_IPSexplicitly, or opt into the old (insecure) behavior withDAGSTER_AUTH_PROXY_TRUST_ALL=true. Default-trust-everything was a mistake in hindsight; this closes it.Cross-pod session revocation without Redis
This one I'm actually proud of. Previously, revoking a session (password change, role change, user delete) only worked reliably with Redis in multi-pod setups - in-memory revocation lists don't propagate across pods, so a compromised session could stay alive on other replicas. v0.4.0 adds asession_versioncolumn on the users table (auto-migrated on upgrade), so revocation is DB-backed and works even on plain SQLite/Postgres/MySQL without Redis in the loop.WebSocket auth for GraphQL subscriptions
Dagster's GraphQL subscriptions run over WebSocket at/graphql.BaseHTTPMiddlewareonly seesscope["type"] == "http", so WebSocket connections were sailing straight past the auth middleware. Rewrote it as pure ASGI middleware to actually intercept both HTTP and WS scopes - also fixes a CORS middleware ordering issue that pure ASGI happens to sidestep.
Other hardening in this release
- CSRF protection on login (double-submit signed cookie)
- XSS escaping on login/403 pages
- Open redirect blocking for protocol-relative URLs (
//evil.com) - Empty password rejection across all backends (this was letting unauthenticated LDAP binds through)
- Dual rate-limiting on username and IP, not just one
- RBAC now deny-by-default for GraphQL mutations AuthKit doesn't recognize yet - new Dagster releases won't silently open a hole until someone audits the new mutation
Full changelog and upgrade notes are in the README.
Where I actually need help
This is the part that matters more than the changelog. AuthKit works via monkey-patching Dagster internals, which means it's inherently a moving target against Dagster's release cycle, and there are a few areas where I don't have the expertise or bandwidth to do it right alone:
- LDAP/Active Directory validation - the LDAP backend is marked experimental for a reason. If you run real AD infrastructure and can test against it (group mapping, nested groups, weird schema edge cases), I need that feedback badly.
- Helm chart - the Kubernetes example works via raw manifests + Makefile. A proper Helm chart is on the roadmap and I'd rather merge a good community PR than write a mediocre one myself.
- Testing against different Dagster versions - Dagster ships fast. If you're pinned to an older or newer version than what CI covers, running the test suite against it and reporting breaks is genuinely high-value.
If any of this overlaps with what you're already running in production, even just opening an issue describing your setup and what broke (or didn't) is useful. PRs obviously welcome, but honest bug reports from real deployments are just as valuable right now.
To be clear on scope: direct OIDC (beyond going through Authelia as a proxy) is not something I'm planning to build myself. If you need Auth0/Keycloak/Okta/Google integrated directly, a PR is very welcome - but don't expect it from me on any timeline.
Installing / trying it
# SQLite for local testing
pip install dagster-authkit[sqlite]
# Postgres + Redis for production
pip install dagster-authkit[postgresql,redis]
dagster-authkit init-db --with-admin
dagster-authkit -f your_pipeline.py -h 0.0.0.0 -p 3000
Or grab one of the ready-to-run examples (quickstart-sqlite, postgresql_redis, authelia SSO stack, or kubernetes) from the repo and make up.
Philosophy, for context
This project follows a "works > perfect" approach - I'd rather ship something that solves the real "no auth on self-hosted Dagster" problem today than sit on a perfect design forever. Monkey-patching is fragile by nature and I say so directly in the docs; this isn't Dagster+, and it's not trying to be. It's a bridge for teams that need real auth now and aren't ready (or don't need) to pay for the enterprise offering.
Repo: https://github.com/maltzsama/dagster-authkit - issues and PRs genuinely welcome, especially on the four areas above.
Comments
No comments yet. Start the discussion.