Skip to content

feat: feature flags for registration, 2FA and passkeys (#66)#79

Merged
andregoepel merged 1 commit into
mainfrom
feat/identity-feature-flags
Jul 4, 2026
Merged

feat: feature flags for registration, 2FA and passkeys (#66)#79
andregoepel merged 1 commit into
mainfrom
feat/identity-feature-flags

Conversation

@andregoepel

Copy link
Copy Markdown
Owner

Fixes #66. Companion to andregoepel/app-foundation#49 (host-side store + admin UI).

What

Lets a host enable/disable registration, 2FA and passkeys. Disabling a feature hides its UI and makes its setup pages/endpoints unreachable by direct URL — not merely hidden. This package defines the seam and does the gating; the host owns persistence.

Abstraction

  • IIdentityFeatureProvider.GetAsync()IdentityFeatureFlags (async; a host impl reads a DB). Enum IdentityFeature { UserRegistration, TwoFactor, Passkey }.
  • Default OptionsIdentityFeatureProvider reads MartenIdentityBlazorOptions (new EnableUserRegistration / EnableTwoFactor / EnablePasskey, all default true), registered via TryAddScoped so a host provider wins. DB value takes precedence — the host implements that in its provider.

Enforcement

  • IdentityFeatureGateMiddleware (app.UseMartenIdentityFeatureGate()) maps request paths to features; when disabled it redirects page navigations to /Account/Login and 404s endpoint/fetch calls (mirrors SetupRedirectMiddleware, including the Sec-Fetch-Dest heuristic). Covers both Razor pages and the passkey minimal-API endpoints.

Graceful gating (approved behavior)

  • Gated: registration entry (Register/RegisterConfirmation/ResendEmailConfirmation), 2FA setup/management pages, passkey management + all passkey login/creation endpoints.
  • Not gated: the login-time 2FA/recovery challenge (LoginWith2fa/LoginWithRecoveryCode) — so a user who already enrolled isn't locked out. Passkey login being gated is safe (password fallback).

UI

  • Login.razor hides the register link and passkey button and skips passkey conditional mediation per the flags.

Tests

  • Middleware: every gated path is blocked when its feature is off (404 for fetch / redirect for document nav) and passes when on; the login-challenge paths are not gated even when 2FA is off; unrelated paths always pass.
  • OptionsIdentityFeatureProvider resolved through real DI returns default + configured values.
  • Login bUnit: register link / passkey button shown when enabled, hidden when their feature is off.
  • Full suite: 187 unit + 97 Blazor + 75 integration; build 0 warnings; CSharpier clean.

Out of scope (app-foundation#49)

DB store, admin settings page and config binding of the flags; hiding host-owned account-nav links (host reads the same provider); bulk-disabling 2FA for existing users.

The consuming app needs to enable/disable identity features via config + an
admin-editable store. The affected UI and backend pages/endpoints live here, so
the gating is supported in this package; the host owns persistence.

Add an IIdentityFeatureProvider abstraction (async snapshot of the three flags)
with an options-backed default (MartenIdentityBlazorOptions gains
EnableUserRegistration/EnableTwoFactor/EnablePasskey, all default true). A host
registers its own provider — whose stored value takes precedence — via the
TryAdd seam.

IdentityFeatureGateMiddleware (UseMartenIdentityFeatureGate) makes a disabled
feature unreachable by direct URL, not just hidden: it maps request paths to
features and, when disabled, redirects page navigations to /Account/Login and
404s endpoint/fetch calls (mirrors SetupRedirectMiddleware). Graceful gating —
registration entry, 2FA setup/management and passkey management + login/creation
endpoints are gated, but the login-time 2FA/recovery challenge stays reachable so
already-enrolled users are not locked out (passkey login falls back to password).

The Login page hides the register link and passkey button (and skips passkey
conditional mediation) per the flags. Adds middleware tests (each gated path
blocked / login challenge not gated / unrelated paths pass), provider-through-DI
tests, and Login bUnit gating tests; documents the flags, the UseMartenIdentity-
FeatureGate wiring and the provider override in the Blazor README.
@andregoepel
andregoepel merged commit 489fd3e into main Jul 4, 2026
3 checks passed
@andregoepel
andregoepel deleted the feat/identity-feature-flags branch July 6, 2026 13:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support feature flags for registration, 2FA and passkeys in identity UI

1 participant