If you are preparing a Strapi deployment for a security review, "how do we enforce MFA on the admin panel?" comes up early. The short answer:
Strapi does not ship a built-in TOTP second factor for local admin accounts. Logging in with an email and password at /admin is a single-factor flow.
That is not the end of the conversation, though. There are three practical routes, and for most teams the first one is both the strongest and the least work.
Option 1: SSO, and let your identity provider enforce MFA
This is the recommended answer for any organisation that already has an identity provider.
Single Sign-On lets administrators authenticate through an external IdP, such as Microsoft Entra ID (Azure AD), Okta, Google Workspace, Auth0, Keycloak, or any OIDC/SAML provider, instead of a local Strapi password. Strapi hands authentication to the IdP, and every policy the IdP enforces applies: TOTP, hardware keys, push approval, conditional access, device compliance, IP restrictions, session lifetime.
You get more than MFA out of it:
- Central offboarding. Disabling someone in the IdP removes their Strapi access. No orphaned admin accounts.
- Role mapping. SSO configuration includes mapping IdP roles onto Strapi admin roles, so permissions follow group membership.
- One audit trail covering every system, not a separate one for the CMS.
Two things to know before you plan around it:
- SSO is available on the CMS Enterprise plan, or as an SSO add-on on the CMS Growth plan. It is not part of the free tier.
- Once SSO is configured you can restrict local password login, so admins cannot bypass the IdP by falling back to email and password. Do configure that. SSO alongside an unrestricted local login is not MFA enforcement, it is an extra login button. The setting is Local authentication lock-out under Global settings > Single Sign-On.
Do not put Super Admin in the local authentication lock-out list. The Strapi docs carry an explicit warning here: if SSO then fails for that account, you have locked yourself out of the admin panel entirely, and the only recovery is to disable the SSO feature, log in with a password, remove Super Admin from the lock-out list, and re-enable SSO. Lock out the editor and author roles; leave at least one break-glass Super Admin on local auth.
Configuration lives under config/admin in the auth.providers array, plus role mapping in the admin panel under Settings → Single Sign-On. Provider-specific walkthroughs are in the SSO providers documentation.
Option 2: A community or commercial 2FA plugin
If SSO is not on the table, whether because of a small team, a self-hosted community-edition project, or no IdP, there are marketplace plugins that add a TOTP challenge to the admin login screen. They typically patch the admin authentication flow to insert a second step after the password check, and store per-user secrets alongside the admin user record.
Evaluate one the way you would evaluate any dependency that sits in your authentication path:
- Is it maintained, and does it declare Strapi 5 support? The admin authentication internals changed between v4 and v5. A plugin that only lists v4 compatibility will break.
- Where are the TOTP secrets stored, and are they encrypted at rest? A plaintext secret column is worse than no second factor, because it creates a false sense of coverage.
- Are there recovery codes, and what happens when someone loses their phone? You need a documented account-recovery path that does not involve editing the database by hand.
- What is the licence and the support model? Several 2FA plugins in this space are commercial with a free trial.
- Does it survive an upgrade? Test it against a Strapi minor upgrade in staging before you rely on it.
Browse the Strapi Marketplace and filter for authentication plugins. Treat whatever you find as a dependency in your threat model, not a checkbox.
Option 3: Put the admin panel behind something that already does MFA
This route is often overlooked and it is genuinely strong, because it stops unauthenticated traffic before it reaches Strapi at all.
Put /admin behind an authenticating proxy:
- Cloudflare Access / Zero Trust in front of the admin path, with your IdP and MFA policy attached.
- Google IAP, AWS ALB with OIDC authentication, or Azure App Service Easy Auth.
- A VPN or Tailscale, with the admin panel not exposed publicly at all.
- oauth2-proxy in front of Nginx, if you are self-hosting.
Combined with a reverse proxy rule that only exposes /api publicly, this gives you defence in depth: an attacker who obtains a Strapi admin password still cannot reach the login form.
A minimal Nginx shape for the split:
# Public API
location /api/ {
proxy_pass http://strapi_upstream;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# Admin panel: restricted at the network layer
location /admin {
allow 203.0.113.0/24; # office / VPN range
deny all;
proxy_pass http://strapi_upstream;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}If you do this, remember to set proxy.koa: true in config/server so Strapi trusts the forwarded headers, and pair app.proxyIpHeader with app.maxIpsCount so the header cannot be spoofed.
What you should do regardless of which route you pick
Whether or not you land a second factor, these are free and they matter:
- Use RBAC properly. Most people who need to edit content do not need Super Admin. Reducing the number of accounts that can install plugins or change settings shrinks the blast radius of a stolen password.
- Turn on Audit Logs (Enterprise) so you can see who did what.
- Keep
ADMIN_JWT_SECRET,APP_KEYS,JWT_SECRET,API_TOKEN_SALT, andENCRYPTION_KEYin your secret manager, unique per environment and never committed. A leakedADMIN_JWT_SECRETlets someone forge an admin session, and no second factor helps once that happens. - Audit administrator accounts regularly:
npx strapi admin:list-usersprints every account with its active and blocked status. Block or delete the ones you do not recognise. - Tighten admin session lifetimes. Strapi 5 manages admin auth as refresh/session token families, configurable under
admin.auth.sessionsinconfig/admin:accessTokenLifespan(default 1800s),maxSessionLifespan(1 day),idleSessionLifespan(2 hours),maxRefreshTokenLifespan(30 days), andidleRefreshTokenLifespan(14 days). Shortening these limits how long a stolen session stays usable, which is the specific risk a second factor is usually bought to cover. Administrators can also list their active sessions and revoke them individually, or revoke all others, from their own account. - Scope and rotate API tokens. A full-access API token is an admin-equivalent credential that no login flow protects.
Tracking the feature
Native 2FA for local admin accounts is a long-standing community request. If it matters to your roadmap, add your vote and your use case on feedback.strapi.io. Deployment context is what makes a request actionable, so say whether you need TOTP, WebAuthn, or enforcement policy.




