Without MFA, a stolen or phished password is sufficient to compromise any account. CWE-308 (Use of Single-Factor Authentication) and OWASP A07 (Identification & Authentication Failures) both flag password-only auth as a systemic weakness. NIST 800-53 IA-2(1) mandates multi-factor authentication for privileged accounts and for any system handling sensitive data. Credential phishing is the most common initial access vector in reported breaches; MFA stops the majority of these attacks even after credentials are compromised. Admin accounts without MFA are an especially high-value target because a single compromise grants full application access.
Medium because MFA absence doesn't directly expose a vulnerability, but it means a stolen password alone — the most commonly leaked credential type — provides full account access.
Implement TOTP-based MFA using otplib. Store the secret encrypted; only mark totpEnabled: true after the user successfully verifies their first code:
import { authenticator } from 'otplib'
// Enrollment: generate and return QR code
const secret = authenticator.generateSecret()
const otpauth = authenticator.keyuri(user.email, 'YourApp', secret)
// Save encrypt(secret) to database with totpEnabled: false
// Verification: check code before enabling
const isValid = authenticator.check(userCode, secret)
if (isValid) await db.user.update({ where: { id }, data: { totpEnabled: true } })
Force MFA enrollment for admin roles on first login. Provide backup codes at enrollment time and store them hashed.
ID: security-hardening.input-validation.mfa-available
Severity: medium
What to look for: Count all authentication flows (login, registration, account recovery). For each, check whether the application supports any form of multi-factor authentication: TOTP (authenticator apps), SMS codes, email codes, WebAuthn/passkeys, or hardware keys. Look for otpauth, speakeasy, otplib dependencies (TOTP), WebAuthn libraries, or managed auth provider MFA settings.
Pass criteria: MFA is available for user accounts, and is enforced for privileged/admin accounts. The MFA implementation includes proper backup codes or recovery mechanisms — at least 1 MFA method (TOTP, SMS, or WebAuthn) available for all user accounts. Report: "X auth flows found, MFA available on Y."
Fail criteria: No MFA option is available to users. Or MFA exists but is not enforced for admin accounts.
Skip (N/A) when: The application is an internal tool with a small, trusted user base and MFA is enforced at the SSO/identity provider level before reaching the app. Or the project is an early prototype not yet handling sensitive data.
Detail on fail: "No MFA implementation found — admin accounts protected only by password" or "TOTP support exists for regular users but admin roles have no MFA enforcement"
Remediation: For TOTP-based MFA using otplib:
import { authenticator } from 'otplib'
import QRCode from 'qrcode'
// Enrollment
const secret = authenticator.generateSecret()
const otpauth = authenticator.keyuri(user.email, 'YourApp', secret)
const qrDataUrl = await QRCode.toDataURL(otpauth)
// Store secret encrypted in database
await db.user.update({
where: { id: user.id },
data: { totpSecret: encrypt(secret), totpEnabled: false }, // not enabled until verified
})
// Verification (after user scans QR and enters first code)
const isValid = authenticator.check(token, secret)
if (isValid) {
await db.user.update({ where: { id: user.id }, data: { totpEnabled: true } })
}
Require MFA during login for accounts with totpEnabled: true, and force it during first privileged action for admin accounts.