MFA Fundamentals

MFA Implementation

Multi-factor authentication requires two or more factors: something you know (password), something you have (phone), or something you are (biometric).

TOTP Implementation

Time-based One-Time Passwords (TOTP) are the most widely deployed MFA method:

import pyotp

import qrcode

import io

import base64

class TOTPManager:

def init(self, issuer="Example Corp"):

self.issuer = issuer

def generate_secret(self):

return pyotp.random_base32()

def get_provisioning_uri(self, email, secret):

totp = pyotp.TOTP(secret)

return totp.provisioning_uri(name=email, issuer_name=self.issuer)

def generate_qr(self, email, secret):

uri = self.get_provisioning_uri(email, secret)

qr = qrcode.make(uri)

buf = io.BytesIO()

qr.save(buf, format="PNG")

return base64.b64encode(buf.getvalue()).decode()

def verify_code(self, secret, code):

totp = pyotp.TOTP(secret)

Allow 1 step before/after for clock drift

return totp.verify(code, valid_window=1)

def get_current_code(self, secret):

totp = pyotp.TOTP(secret)

return totp.now()

SMS-Based MFA

import random

import string

class SMSMFAManager:

def init(self, sms_provider):

self.sms_provider = sms_provider

self.codes = {} # phone -> {code, expires_at}

def send_code(self, phone):

code = ''.join(random.choices(string.digits, k=6))

expiry = datetime.utcnow() + timedelta(minutes=5)

self.codes[phone] = {"code": code, "expires_at": expiry}

self.sms_provider.send(phone, f"Your code is: {code}")

return True

def verify_code(self, phone, code):

stored = self.codes.get(phone)

if not stored:

return False

if datetime.utcnow() > stored["expires_at"]:

del self.codes[phone]

return False

if stored["code"] != code:

return False

del self.codes[phone]

return True

Push Notification MFA

// Server-side push notification

async function sendPushChallenge(userId, deviceToken) {

const challenge = crypto.randomUUID();

// Store challenge

await redis.set(

mfa:push:${challenge},

userId,

"EX",

120 // 2 minute expiry

);

// Send push notification

await admin.messaging().send({

token: deviceToken,

data: {

type: "MFA_CHALLENGE",

challenge: challenge,

appName: "Example App",

timestamp: Date.now().toString()

}

});

return challenge;

}

// Client-side approval

async function respondToChallenge(challengeId, approved) {

await fetch("/api/auth/mfa/push/respond", {

method: "POST",

body: JSON.stringify({

challenge: challengeId,

approved: approved,

deviceId: deviceId

})

});

}

Backup Codes

Always provide backup codes when users enroll in MFA:

def generate_backup_codes(count=10):

codes = []

for _ in range(count):

code = '-'.join([

''.join(random.choices(string.ascii_uppercase + string.digits, k=4))

for _ in range(3)

])

hashed = hashlib.sha256(code.encode()).hexdigest()

codes.append({"raw": code, "hashed": hashed})

return codes

Enforcement Strategy

mfa_enforcement:

all_users: true

grace_period: 30_days

exclude_service_accounts: true

risk_based_prompting:

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- new_device: prompt_mfa

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- new_location: prompt_mfa

\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\- sensitive_action: require_mfa

recovery:

backup_codes: 10

admin_recovery: "verify_with_id"

recovery_timeout: 24_hours

Conclusion

MFA is essential but must be implemented thoughtfully. TOTP offers the best balance of security and usability. Provide backup codes during enrollment. Consider risk-based prompting rather than requiring MFA on every request. Guide users toward authenticator apps over SMS when possible.