How to Set Up Multi-Factor Authentication (MFA) for Organizations in Logto
Logto enforces MFA for organization members by setting the is_mfa_required flag on the organization and configuring the global organizationRequiredMfaPolicy to Mandatory, which triggers the core MFA handler to verify bound factors before allowing sign-in.
Setting up multi-factor authentication (MFA) for organizations in Logto allows you to require that every member of a specific organization register an MFA factor before accessing protected resources. This feature is built on top of Logto’s existing MFA subsystem and is controlled through a combination of database-level flags and global sign-in experience policies. Whether you manage multi-tenant SaaS applications or need compliance-grade security for specific business units, organization-level MFA enforcement ensures that users cannot bypass secondary authentication when belonging to sensitive organizations.
Prerequisites
Logto introduced organization-level MFA enforcement in version 1.36.0. Ensure your deployment is running this version or later before configuring these settings, as the required database alterations (including the is_mfa_required column) are not present in earlier releases.
Understanding the Two-Layer Configuration
Organization MFA in Logto operates through two distinct configuration layers that must align for enforcement to trigger:
is_mfa_required on the Organization
- Location:
packages/schemas/tables/organizations.sql - Effect: Marks a specific organization as requiring MFA for its members
organizationRequiredMfaPolicy in Sign-In Experience
- Location:
packages/schemas/src/foundations/jsonb-types/sign-in-experience.ts - Options:
NoPrompt(disabled),Adaptive(risk-based), orMandatory(strict enforcement) - Effect: Determines whether the organization-level requirement is actually enforced during authentication
When both the organization flag is true and the global policy is set to Mandatory, Logto’s core MFA class (packages/core/src/routes/experience/classes/mfa.ts) executes the isMfaRequiredByUserOrganizations method to validate that the user has at least one active MFA factor (TOTP, WebAuthn, or Backup Code).
Step-by-Step Setup Guide
Enable MFA Requirement on the Organization
You can toggle the MFA requirement using the Admin Console or the Management API. The UI toggle is implemented in packages/console/src/pages/Mfa/MfaForm/utils.ts, while the underlying state is stored in the is_mfa_required column of the organizations table.
Using the Management API:
curl -X PATCH "https://<logto-host>/api/organizations/<ORG_ID>" \
-H "Authorization: Bearer <MANAGEMENT_API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"isMfaRequired": true}'
Configure the Global MFA Policy
Set the organizationRequiredMfaPolicy to Mandatory in the sign-in experience configuration. This global setting is read from the sign_in_experiences table and validated by the mfaGuard in packages/schemas/src/foundations/jsonb-types/sign-in-experience.ts.
Using the Management API:
curl -X PATCH "https://<logto-host>/api/sign-in-experience" \
-H "Authorization: Bearer <MANAGEMENT_API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"mfa": {"organizationRequiredMfaPolicy": "Mandatory"}}'
If you prefer a hybrid approach where only specific organizations enforce MFA while others remain optional, keep the policy at NoPrompt and rely solely on the per-organization isMfaRequired flags.
Verify Enforcement
Sign in as a user who belongs to the organization. If the user has no MFA factors bound, Logto returns a 422 response with the error code session.mfa.require_mfa_verification. The front-end automatically redirects the user to the MFA setup page where they can enroll TOTP, WebAuthn, or backup codes.
How Organization MFA Enforcement Works
The Database Schema
The organizations table in packages/schemas/tables/organizations.sql defines the is_mfa_required boolean column. This column is checked during the authentication flow by queries located in packages/core/src/queries/organizations.ts.
The Core MFA Validation Logic
The enforcement logic resides in packages/core/src/routes/experience/classes/mfa.ts. When a user attempts to sign in, the system:
- Reads the
organizationRequiredMfaPolicyfrom the sign-in experience settings - Executes
isMfaRequiredByUserOrganizationsto check if the user belongs to any organization withis_mfa_required = true - Calls
getUserMfaFactorsto verify active bound factors - Throws a
RequestErrorwithsession.mfa.require_mfa_verificationif the user lacks MFA credentials
The Sign-In Experience Configuration
The mfa JSONB column in the sign_in_experiences table controls both the policy and available factors. You can restrict which MFA methods users may register by configuring the mfa.factors array:
curl -X PATCH "https://<logto-host>/api/sign-in-experience" \
-H "Authorization: Bearer <MANAGEMENT_API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"mfa": {"factors": ["Totp", "WebAuthn"]}}'
Code Examples
Enabling Organization MFA via Node.js SDK
import fetch from 'node-fetch';
const managementToken = '<MANAGEMENT_API_TOKEN>';
const orgId = '<ORG_ID>';
const logtoUrl = 'https://logto.example.com';
await fetch(`${logtoUrl}/api/organizations/${orgId}`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${managementToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ isMfaRequired: true }),
});
Setting the Mandatory Policy Programmatically
await fetch(`${logtoUrl}/api/sign-in-experience`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${managementToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
mfa: {
organizationRequiredMfaPolicy: 'Mandatory',
},
}),
});
Handling MFA Requirements in React Applications
import { useEffect } from 'react';
import { useLogto } from '@logto/react';
function MfaGuard() {
const { getAccessToken } = useLogto();
useEffect(() => {
async function checkMfa() {
const token = await getAccessToken();
const response = await fetch('/api/me', {
headers: { Authorization: `Bearer ${token}` },
});
const { mfaStatus } = await response.json();
if (mfaStatus === 'needSetup') {
window.location.href = '/mfa/setup';
}
}
checkMfa();
}, []);
}
Enrolling a TOTP Factor via API
curl -X POST "https://<logto-host>/api/my-account/mfa/totp" \
-H "Authorization: Bearer <USER_ACCESS_TOKEN>" \
-H "Content-Type: application/json" \
-d '{"code":"123456"}'
Summary
- Organization MFA requires two settings: the
is_mfa_requiredflag on the organization table and the globalorganizationRequiredMfaPolicyset toMandatoryin the sign-in experience configuration. - Core enforcement happens in
packages/core/src/routes/experience/classes/mfa.tsthrough theisMfaRequiredByUserOrganizationsmethod, which queries theorganizationstable and validates bound MFA factors. - Configuration options include the Admin Console UI (
packages/console/src/pages/Mfa/MfaForm/utils.ts) or direct Management API calls for automation. - Supported factors include TOTP, WebAuthn, and Backup Codes, configurable via the
mfa.factorsarray in the sign-in experience settings.
Frequently Asked Questions
What Logto version supports organization-level MFA?
Organization-level MFA enforcement was introduced in Logto 1.36.0. Earlier versions lack the is_mfa_required column in the organizations table and the organizationRequiredMfaPolicy configuration option. Check your version by examining the alteration records or the logto_version metadata in your database.
What happens if a user belongs to multiple organizations with different MFA requirements?
Logto evaluates all organizations that the user belongs to during the sign-in process. If any organization has is_mfa_required = true and the global policy is set to Mandatory, the user must complete MFA verification regardless of other memberships. The isMfaRequiredByUserOrganizations method in packages/core/src/routes/experience/classes/mfa.ts performs this aggregate check.
Can I use the Admin Console instead of the Management API to configure MFA?
Yes. The Logto Admin Console provides a UI toggle for enabling organization MFA, implemented in packages/console/src/pages/Mfa/MfaForm/utils.ts. Navigate to the organization details page and enable the Require MFA switch. However, you must still configure the global organizationRequiredMfaPolicy to Mandatory via the Sign-in Experience settings to activate enforcement.
What MFA factors are supported for organization enforcement?
Logto supports TOTP (Time-based One-Time Password), WebAuthn (biometric/hardware keys), and Backup Codes for organization-level MFA. You can restrict which factors are available by modifying the mfa.factors array in the sign-in experience configuration. The validation logic in packages/core/src/routes/experience/classes/mfa.ts accepts any of these factors as satisfying the organization requirement.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →