mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
docs(security): note that required-MFA prompts but does not wall the API
The "Require a second factor" policy redirects web users to enrollment but does not block direct API or native (Bearer) access for an account that has not yet enrolled — a deliberate lockout-safety choice. Make that explicit: spell it out in the admin toggle description, add a code comment at the toggle, and add an operator runbook (docs/ops/mfa-enforcement.md) describing the boundary.
This commit is contained in:
1 parent
7e63794e81
commit
36c899b1c8
8 files changed
+43
-7
No files matched your search
@@ -0,0 +1,34 @@
|
||||
# Require a second factor (operator)
|
||||
|
||||
The admin settings expose a **Require a second factor** policy — instance-wide
|
||||
under General settings, and as a per-user override on the user detail page. The
|
||||
effective requirement for an account is the OR of the per-user override and the
|
||||
instance-wide policy.
|
||||
|
||||
## What enforcement does — and does not — do
|
||||
|
||||
Enforcement is a **guidance nudge for web sessions, not a hard API wall.**
|
||||
|
||||
- When the policy is on, any account that signs in **on the web** without an
|
||||
active second factor is redirected to enrollment after authentication. It
|
||||
cannot reach the rest of the app until it enrolls.
|
||||
- Enforcement does **not** block direct API or native (Bearer-token) access for
|
||||
an account that has not yet enrolled. A token-authenticated client keeps
|
||||
working until the user enrolls a factor of their own accord.
|
||||
|
||||
This is deliberate. A hard API wall on a not-yet-enrolled account would lock a
|
||||
native client (or an automation using a long-lived token) out of its own data
|
||||
with no in-band way to enrol, and there is no server-side path to mint a second
|
||||
factor on the user's behalf. The step-up gates that protect destructive actions
|
||||
(MFA disable, recovery-code regeneration, account deletion, encrypted export)
|
||||
remain cookie-only and are unaffected by this policy — they apply to accounts
|
||||
that have actually enrolled a factor.
|
||||
|
||||
## Operator guidance
|
||||
|
||||
- Treat the policy as a strong prompt that drives adoption, not as a control
|
||||
that retroactively secures every transport.
|
||||
- To hard-gate a specific account's API access, the lever is the account
|
||||
itself (disable it, or rotate/revoke its tokens), not the MFA-required flag.
|
||||
- The redirect clears the moment the user completes enrollment; no operator
|
||||
action is needed afterwards.
|
||||
+1
-1
@@ -5689,7 +5689,7 @@
|
||||
"carrier": "Anbieter",
|
||||
"carrierUnavailableGeoFallback": "{location} — Anbieter nicht verfügbar",
|
||||
"mfaRequired": "Zweiten Faktor verlangen",
|
||||
"mfaRequiredDescription": "Jedes Konto ohne aktiven zweiten Faktor wird nach der Anmeldung zur Einrichtung geleitet.",
|
||||
"mfaRequiredDescription": "Jedes Konto ohne aktiven zweiten Faktor wird nach der Anmeldung zur Einrichtung geleitet. Das fordert Web-Nutzer zur Einrichtung auf – es blockiert jedoch keinen direkten API- oder nativen (Bearer-)Zugriff für noch nicht eingerichtete Konten.",
|
||||
"mfaEnforcedOn": "MFA an",
|
||||
"mfaEnforcedOff": "MFA aus",
|
||||
"mfaEnforcedOnHint": "Für diesen Nutzer ist ein zweiter Faktor erforderlich. Klicken, um die Anforderung aufzuheben.",
|
||||
|
||||
+1
-1
@@ -5689,7 +5689,7 @@
|
||||
"carrier": "Carrier",
|
||||
"carrierUnavailableGeoFallback": "{location} — carrier unavailable",
|
||||
"mfaRequired": "Require a second factor",
|
||||
"mfaRequiredDescription": "Every account without an active second factor is sent to enrollment after sign-in.",
|
||||
"mfaRequiredDescription": "Every account without an active second factor is sent to enrollment after sign-in. This prompts web users to enroll — it does not block direct API or native (Bearer) access for accounts not yet enrolled.",
|
||||
"mfaEnforcedOn": "MFA on",
|
||||
"mfaEnforcedOff": "MFA off",
|
||||
"mfaEnforcedOnHint": "A second factor is required for this user. Click to stop requiring it.",
|
||||
|
||||
+1
-1
@@ -5689,7 +5689,7 @@
|
||||
"carrier": "Operador",
|
||||
"carrierUnavailableGeoFallback": "{location} — operador no disponible",
|
||||
"mfaRequired": "Exigir un segundo factor",
|
||||
"mfaRequiredDescription": "Toda cuenta sin un segundo factor activo se dirige a la configuración tras iniciar sesión.",
|
||||
"mfaRequiredDescription": "Cada cuenta sin un segundo factor activo se dirige a la configuración tras iniciar sesión. Esto pide a los usuarios web que lo configuren, pero no bloquea el acceso directo por API o nativo (Bearer) de las cuentas que aún no lo tienen.",
|
||||
"mfaEnforcedOn": "MFA activado",
|
||||
"mfaEnforcedOff": "MFA desactivado",
|
||||
"mfaEnforcedOnHint": "Este usuario debe usar un segundo factor. Haz clic para dejar de exigirlo.",
|
||||
|
||||
+1
-1
@@ -5689,7 +5689,7 @@
|
||||
"carrier": "Opérateur",
|
||||
"carrierUnavailableGeoFallback": "{location} — opérateur indisponible",
|
||||
"mfaRequired": "Exiger un second facteur",
|
||||
"mfaRequiredDescription": "Tout compte sans second facteur actif est dirigé vers la configuration après la connexion.",
|
||||
"mfaRequiredDescription": "Chaque compte sans deuxième facteur actif est dirigé vers la configuration après la connexion. Cela invite les utilisateurs web à l'activer, mais ne bloque pas l'accès direct par API ou natif (Bearer) pour les comptes pas encore configurés.",
|
||||
"mfaEnforcedOn": "MFA activé",
|
||||
"mfaEnforcedOff": "MFA désactivé",
|
||||
"mfaEnforcedOnHint": "Un second facteur est requis pour cet utilisateur. Cliquez pour ne plus l'exiger.",
|
||||
|
||||
+1
-1
@@ -5689,7 +5689,7 @@
|
||||
"carrier": "Operatore",
|
||||
"carrierUnavailableGeoFallback": "{location} — operatore non disponibile",
|
||||
"mfaRequired": "Richiedi un secondo fattore",
|
||||
"mfaRequiredDescription": "Ogni account senza un secondo fattore attivo viene indirizzato alla configurazione dopo l'accesso.",
|
||||
"mfaRequiredDescription": "Ogni account senza un secondo fattore attivo viene indirizzato alla configurazione dopo l'accesso. Questo invita gli utenti web ad attivarlo, ma non blocca l'accesso diretto via API o nativo (Bearer) per gli account non ancora configurati.",
|
||||
"mfaEnforcedOn": "MFA attivo",
|
||||
"mfaEnforcedOff": "MFA disattivato",
|
||||
"mfaEnforcedOnHint": "Per questo utente è richiesto un secondo fattore. Clicca per non richiederlo più.",
|
||||
|
||||
+1
-1
@@ -5689,7 +5689,7 @@
|
||||
"carrier": "Operator",
|
||||
"carrierUnavailableGeoFallback": "{location} — operator niedostępny",
|
||||
"mfaRequired": "Wymagaj drugiego składnika",
|
||||
"mfaRequiredDescription": "Każde konto bez aktywnego drugiego składnika jest kierowane do konfiguracji po zalogowaniu.",
|
||||
"mfaRequiredDescription": "Każde konto bez aktywnego drugiego składnika jest po zalogowaniu kierowane do konfiguracji. To zachęca użytkowników sieci do włączenia go, ale nie blokuje bezpośredniego dostępu przez API ani natywnego (Bearer) dla kont jeszcze nieskonfigurowanych.",
|
||||
"mfaEnforcedOn": "MFA wł.",
|
||||
"mfaEnforcedOff": "MFA wył.",
|
||||
"mfaEnforcedOnHint": "Ten użytkownik musi używać drugiego składnika. Kliknij, aby przestać go wymagać.",
|
||||
|
||||
@@ -45,7 +45,9 @@ export function GeneralSettingsSection() {
|
||||
|
||||
{/* v1.23 — instance-wide "require a second factor" policy. Every
|
||||
account without an active factor is sent to forced enrollment after
|
||||
sign-in. */}
|
||||
sign-in. This is a web-session nudge, not an API wall: direct API /
|
||||
native (Bearer) access for a not-yet-enrolled account is not blocked.
|
||||
See docs/ops/mfa-enforcement.md. */}
|
||||
<SettingsToggle
|
||||
label={t("admin.mfaRequired")}
|
||||
description={t("admin.mfaRequiredDescription")}
|
||||
|
||||
Reference in new issue
Block a user