SyntaxStudy
Sign Up
Web Security Multi-Factor Authentication (MFA) Implementation
Web Security Beginner 1 min read

Multi-Factor Authentication (MFA) Implementation

Multi-factor authentication (MFA) requires users to prove their identity using at least two factors from different categories: something they know (password), something they have (TOTP app, hardware key), or something they are (biometric). Even if a password is compromised through phishing or a data breach, an attacker without the second factor cannot access the account. MFA is the single most effective control for preventing account takeover attacks. Time-based One-Time Password (TOTP) — standardised in RFC 6238 — is the most widely deployed software MFA method. The server and client share a secret key. Every 30 seconds, both independently compute HMAC-SHA1(secret, floor(unix_time / 30)) and display the 6-digit truncated result. Because the computation is time-bound and uses a shared secret, a valid code is usable only once and expires in 30 seconds. TOTP is supported by Google Authenticator, Authy, 1Password, and Bitwarden. Hardware security keys based on the FIDO2/WebAuthn standard are phishing-resistant MFA because the key cryptographically binds its response to the relying party's origin. Unlike TOTP codes, which can be intercepted by a real-time phishing proxy, WebAuthn keys cannot be used on a lookalike domain. For highest-security deployments — VPNs, admin panels, financial transactions — hardware keys (YubiKey, Google Titan) are the gold standard.
Example
<?php
// TOTP MFA with the pragmarx/google2fa-laravel package

// 1. Generate and store a secret key during MFA enrollment
use PragmaRX\Google2FALaravel\Facade as Google2FA;

// Enrollment: generate secret and display QR code
$secret = Google2FA::generateSecretKey(32);
// Store $secret encrypted in the users table (never plain-text)
$user->update(['totp_secret' => encrypt($secret)]);

$qrCodeUrl = Google2FA::getQRCodeUrl(
    config('app.name'),
    $user->email,
    $secret
);
// Render QR code as SVG or PNG for the user to scan

// 2. Verify a code at login
function verifyTOTP(User $user, string $code): bool
{
    $secret = decrypt($user->totp_secret);
    // Allow 1 window (30s) of drift for clock skew
    return Google2FA::verifyKey($secret, $code, 1);
}

// 3. Mark session as MFA-verified
if (verifyTOTP($user, $request->input('totp_code'))) {
    session(['mfa_verified' => true, 'mfa_verified_at' => now()->timestamp]);
    return redirect()->intended('/dashboard');
}

// 4. Middleware to require MFA on sensitive routes
// if (!session('mfa_verified')) redirect('/mfa/challenge');

// Recovery codes — generate 8 one-time codes at enrollment
$recoveryCodes = collect(range(1, 8))->map(fn() => bin2hex(random_bytes(10)))->all();
// Store hashed recovery codes; delete after use