Requiring two-factor

Make two-factor authentication mandatory for an organization's members, limit it to authenticator apps, and decide how long a device may be remembered.

Each user decides whether to turn on two-factor authentication for their own account. An organization can also require it: every member must have a factor before they can do anything in that organization. The requirement belongs to the organization, so a person in three organizations meets the strictest one only while acting in it.

What a member experiences

A member who already has a factor notices nothing. A member who has none is not locked out, because setting up a factor needs a session. Instead:

They get a restricted session

Signing in (or switching into the organization) succeeds, and the response carries mfaEnrollmentRequired: true with the organization asking:

{
  "mfaEnrollmentRequired": true,
  "mfaEnrollment": {
    "orgUid": "0199a5f0-9e33-7d42-b6a8-2f1c0e7d5b19",
    "orgName": "Northwind Clinics",
    "allowedKinds": ["totp"]
  },
  "auth": { "accessToken": "eyJhbGciOi...", "refreshToken": "eyJhbGciOi...", "activeOrgUid": "0199a5f0-9e33-7d42-b6a8-2f1c0e7d5b19" }
}

The session works only for getting out of that state

It can enroll and manage factors, read the organization's requirement, refresh, sign out, list the user's organizations and switch to another one. Anything else answers 403 MFA_ENROLLMENT_REQUIRED.

Once a factor is confirmed, refresh

The next refresh issues an ordinary session.

Never sign the user out on MFA_ENROLLMENT_REQUIRED

Route them to your enrollment screen instead. Signing them out only brings them back to the same state on their next sign-in. The other way out is switching to an organization that does not require 2FA, which is why the organization list stays reachable.

The requirement is checked on every sign-in and every refresh, including the refresh that switches organization. Turning it on therefore reaches every existing session within one access token lifetime (15 minutes), without signing anyone out, and switching organization can never step around it.

Setting the requirement

An organization's owner and administrators set it for their active organization. Any member can read it, so a member being asked to enroll can see which organization is asking and what counts.

# Read
curl "$AUTHORIC_URL/$APP_UID/auth/org-security" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Require 2FA, authenticator apps only, remember devices for 14 days
curl -X POST "$AUTHORIC_URL/$APP_UID/auth/org-security" \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "mfaRequired": true, "allowedKinds": ["totp"], "rememberDeviceDays": 14 }'
{
  "orgUid": "0199a5f0-9e33-7d42-b6a8-2f1c0e7d5b19",
  "orgName": "Northwind Clinics",
  "mfaRequired": true,
  "allowedKinds": ["totp"],
  "callerSatisfies": true,
  "rememberDeviceDays": 14,
  "rememberDeviceDefaultDays": 30,
  "rememberDeviceMaxDays": 90
}
FieldMeaning
mfaRequiredRequired. true requires a factor of every member; false clears the requirement.
allowedKindsWhich factors count: ["totp"] for authenticator apps only (the usual answer to SIM-swap risk), or ["totp", "sms"]. Omit or send null for any kind. An empty list is refused rather than read as "any".
rememberDeviceDaysHow long a device may skip the challenge, 0 to 90. 0 forbids remembering devices and forgets the ones already remembered for this organization. Omit it to leave it unchanged; null (never set) means the 30-day default.
callerSatisfiesOn a read: whether the caller already has a factor that counts, so your UI can explain a disabled switch before anyone clicks it.

Turning it on is guarded; turning it off is not

Requiring 2FA is refused for a caller who has no qualifying factor of their own (409 ORG_MFA_ENABLE_BLOCKED): otherwise the first person to use the setting would be the first person it locks out. Clearing it is always allowed, so an organization that has boxed itself in can be rescued by whoever can still get in.

A member's factor counts if it is confirmed, whether or not it can be reached right now. A phone factor still satisfies the requirement when your plan's SMS allowance has run out; the user is offered their other factors or recovery codes at sign-in instead.

Your own Authoric organization

The same switches exist for the organization you sign in to the console with, under Settings › General, with the same rules: the requirement applies on every refresh, a member without a factor is held on a setup screen rather than signed out, and you cannot turn it on until you have a factor yourself.

Errors to branch on

CodeStatusMeaning
MFA_ENROLLMENT_REQUIRED403This session owes a factor for its organization. Send the user to enroll.
ORG_MFA_ENABLE_BLOCKED409Set up your own factor before requiring one.
MFA_LAST_FACTOR409Pausing this factor would leave nothing that satisfies the organization.

What's next

On this page