Releases: cocoar-dev/modgud
Release list
v0.5.0
First public release of Modgud — a self-hosted multi-tenant Identity Provider for ASP.NET Core. OAuth 2.0 / OpenID Connect server with database-per-realm isolation, multi-app permission catalogs, Keycloak-style resource_access emission, the full 2FA spectrum, GDPR self-service, and OpenTelemetry observability built in.
This is the first release since the repo went public, and it reflects roughly a year of focused work. It is not 1.0. The Roadmap is the canonical view of what's shipped, what's intentionally missing, and what's coming next.
Highlights
Multi-tenancy by design
Every realm gets its own PostgreSQL database via Marten's MasterTableTenancy. Domain-based routing maps Host headers to tenants — no tenant_id columns, no path-prefix acrobatics, no cross-realm leaks possible. A realm-create operation provisions a fresh database and seeds default OAuth scopes + the Internal login provider.
Multi-app permission model
Apps are first-class. Permissions are 2-segment (<resource>:<action>) inside an app's catalog (e.g. modgud:user:read, acme-tasks:todo:write). Two bypass tiers (<resource>:admin, realm:admin), no more. Roles bind to one App; groups carry a BoundTo activation list. The IdP pre-expands the bypass at token-issue time so resource servers do exact-match lookups.
Keycloak-style resource_access on UserInfo
Per-audience blocks emitted on /connect/userinfo with per-resource-server subset narrowing — drop-in for Keycloak-shaped client libraries. The Modgud.Client.AspNetCore NuGet package flattens the right block into ClaimTypes.Role so [Authorize(Roles = "...")] works without per-endpoint plumbing.
Full 2FA spectrum
TOTP, Email-OTP, FIDO2/Passkey, Magic Link, recovery codes — combinable per user. A 2FA-enforcement middleware with grace periods and per-user overrides. Configurable authentication-level policies (password-only, secure-login-with-2FA, passwordless-only).
OAuth 2.0 / OpenID Connect server (OpenIddict 7)
- Authorization Code + PKCE, Client Credentials, Refresh Token, Device Code (RFC 8628)
- Reference tokens by default (instantly revocable); per-client JWT switch when stateless verification matters
- Per-realm issuer and discovery document at
https://<realm>/.well-known/openid-configuration - Dynamic Client Registration (RFC 7591) with triple opt-in (realm master + per-API + per-scope), audience-target containment, full audit-event trail
- Service accounts as first-class principals —
client_credentials-only OAuth clients linked 1:N to aServiceAccountso audit logs and the Group → Role → Permission chain work the same for machines and humans
OIDC federation
Microsoft Entra ID, Google, any OIDC IdP. JIT user provisioning + JavaScript claim-mapping (UserUpdateScript) for transforming external claims into Modgud's local user shape on each login.
GDPR-ready
Article-20 self-service export. Three-step account deletion with confirmation token. Marten data-masking + ArchiveStream for irreversible PII erase that still preserves audit-chain integrity. Profile change-request flow with admin approval and email-ownership double-opt-in (configurable per realm).
Observability built in
OpenTelemetry metrics + traces. Prometheus scrape endpoint (Bearer-gated). Custom IdP meter (login attempts, token issuance, realm operations, …). In-app live activity feed.
Operations
- Per-realm DataProtection keys persisted in the tenant DB so cookies and antiforgery tokens survive container restarts and never cross realms
- Quartz-scheduled background jobs with admin surface — schedules, history, manual trigger
- Operator inbox for system notifications + per-kind retention
- Per-realm branding — logo, favicon, primary color, product name — and an asset library (BYTEA-backed, SVG-sanitised, 2 MB cap, ETag-served via
/api/assets/{id}) - Page-builder editor (Beta, feature-flagged) for login / logout / forgot-password customisation
- Recovery CLI for break-glass admin operations —
bootstrap-admin,set-email,magic-link,reset-2fa,list,rebuild-projections,realm-add-domain - Auth Log — Serilog-sink-backed audit trail with 7-day retention per realm
Security posture
Apache-2.0-licensed. Dependency audit, CodeQL, secret-scanning + push-protection, and SAST analyzers all wired into CI. JsEval-fuzzing run against the membership-script attack surface. PII-masking convention for logs. CodeQL alerts on the first public scan: 32 findings, all triaged as false positives with documented rationale (see dev-docs/codeql-triage.md).
What's not in this release
Set expectations honestly. These are tracked on the Roadmap:
- Multi-instance HA — Modgud runs as a single instance today. Per-tenant DataProtection keys and the Marten outbox already cover the "restart = everyone logged out" class of bugs, but real HA needs shared state (Redis or equivalent) for SignalR backplane and distributed rate-limiting plus a failover test rig.
- Realm backup / restore / DR tooling —
pg_dump-per-tenant works today; the managed tooling around it (scheduling, verification, restore-into-new-realm, PITR) doesn't yet. - SAML + LDAP federation — the
LoginProvideraggregate reserves theSaml,Ldap, andKerberostype values; handlers come next. - NodaTime time domain + scheduled operations — admin-defined future actions like "deactivate this user on 2026-06-27 at 18:00" need a
LocalDateTime + IANA zonemodel, not a UTC instant (18:00 in which timezone? what when EU drops DST?). The migration moves the domain to NodaTime and unlocks scheduled user deactivation, time-boxed group memberships, scheduled credential rotation, GDPR retention sweeps, password-expiry policies with calendar semantics. Pre-1.0 is the cheapest moment to do this. Plan captured. - HSM/KMS for signing keys, SCIM provisioning, step-up authentication, risk-based authentication — all parked, prioritised on the roadmap.
Get it
Docker image (recommended for evaluation)
docker pull ghcr.io/cocoar-dev/modgud:0.5.0Tags published: 0.5.0, 0.5, 0, latest, production.
For a complete docker compose setup with PostgreSQL, see the Quickstart — from docker compose up to first login in about ten minutes.
Client library (consume Modgud from your ASP.NET Core app)
dotnet add package Modgud.Client.AspNetCore --version 0.5.0Wires up cookie-or-OIDC auth + the resource_access IClaimsTransformation so [Authorize(Roles = "...")] works end-to-end. See the integration guide.
Documentation
Full docs at https://docs.cocoar.dev/modgud/ (unversioned URLs always point to the latest release; add /v0.5/ to the path if you want this release specifically):
- Concepts — realms, apps, permissions, OAuth, tokens, the mental model
- Getting Started — prerequisites, quickstart, first-time setup
- Operate — deployment, observability, recovery CLI, feature flags
- Integrate — plug your ASP.NET Core app into Modgud
- Administer — users, groups, roles, OAuth clients, login providers
- Reference — OAuth / Auth / Admin / Realm endpoint reference
- Roadmap
Feedback
PRs welcome for typos and small fixes — for anything bigger, please open a Discussion first. The Contributing guide has the ground rules.
Security issues do not go through the public issue tracker — see SECURITY.md for the private channel.
About the name
Modgud takes its name from Móðguðr, the watcher of Gjallarbrú in Norse mythology — a bridge between worlds, where she challenged every traveler with the same question an IdP asks: "Who are you, and what brings you here?"
Licensed under Apache-2.0. "Modgud" and the Modgud shield are trademarks of COCOAR e.U. — see TRADEMARK.md for the practical rules.