Deploy & operate

Admin account security

Since v1.25 the admin has two-factor sign-in, a device list and an audit log built in, no plugin needed (WordPress needs Wordfence, WP 2FA, Simple History and the like).

Two-factor sign-in (2FA)

Every admin account turns it on under the top-right menu → Account security (/admin/account):

  1. "Turn on two-factor sign-in", scan the QR code with an authenticator app (Google Authenticator, Microsoft Authenticator, 1Password, Authy, ...);
  2. confirm with the 6-digit code the app shows;
  3. save the 10 recovery codes (shown once). Without the phone, each one signs in once instead of a code.

From then on, signing in asks for a code (or a recovery code) after the password. A code works once; codes and recovery codes are rate limited.

  • Turning it off or creating new recovery codes asks for the current password (turning off also for a code or a recovery code).
  • Admins can "Reset two-factor sign-in" for a user who lost their phone in Users (which also signs that user out everywhere); the user sets it up again.
  • The secret is stored encrypted (AES-GCM, key derived from NUXT_JWT_SECRET), so a database dump alone does not reveal it. Changing NUXT_JWT_SECRET invalidates existing 2FA setups: users sign in with a recovery code, or an admin resets them.
  • If the only admin loses both phone and recovery codes, delete that user's row in the cms_user_security table.
  • Accounts with 2FA that use POST /api/auth/token for API tokens send a code (authenticator or recovery code) too.
  • On the demo site (NUXT_PUBLIC_DEMO_MODE) the shared demo account's security settings are locked.

A site's own login page reaches the second step (/admin/verify) by itself as long as it calls useAuth().login() (every official template does; nuxtcms doctor checks it).

Signed-in devices

The Account security page lists where the account is signed in: browser and system, IP address, country (on Cloudflare), sign-in time and last activity.

  • Sign out one device, or all other devices (sign-ins from before the upgrade included);
  • a password change signs the other devices out and keeps this one;
  • admins can sign a user out everywhere from the Users list.

Changing the password

Everyone (editors too) changes their own password on the Account security page with the current password; the new one needs at least 8 characters.

Audit log

Admin → Audit log (/admin/audit, admins only) records:

  • sign-ins, failed sign-ins (with the e-mail typed), sign-outs, API tokens;
  • 2FA on / off / wrong code, recovery code used, new recovery codes, password changes, devices signed out;
  • every admin change (all POST /api/admin/**, plugin admin APIs included): who, which resource, which id, which fields. Only field names and short labels (title, slug, e-mail...) are kept, never content or the values of secret fields (their names carry a *).

Filter by action, user / item / IP and dates, and export CSV (up to 10,000 rows, formula-safe). Entries are kept for 180 days and pruned by the cron (/api/cron/dispatch), which also removes sign-ins that ended 30 days ago.

Upgrading

New tables user_security, user_sessions, audit_logs, redirects and not_found_log (migration 0017, applied by upgrade.mjs / nuxtcms fleet upgrade). Sessions from before the upgrade stay signed in but are not listed as devices.