Step 4: Handle MFA Response
β± 5 minProcess the MFA verification result and implement your security logic.
MFA Response Structure
interface MfaResult {
success: boolean;
payload: [{
verified: boolean;
method: 'totp' | 'email' | 'hardware_key';
verifiedAt: string; // ISO timestamp
}];
}Basic Handling
const mfaResult = await transcodes.openAuthMfaModal();
if (mfaResult.success) {
const { method, verifiedAt } = mfaResult.payload[0];
console.log(`Verified via ${method} at ${verifiedAt}`);
// Proceed with protected action
await performSensitiveAction();
} else {
// User cancelled or verification failed
console.log('MFA verification not completed');
}MFA Verification Token
After successful MFA, you can get a verification token to send to your server:
const mfaResult = await transcodes.openAuthMfaModal();
if (mfaResult.success) {
// Get the MFA verification token
const mfaToken = await transcodes.token.getMfaToken();
// Send to your server with the protected request
const response = await fetch('/api/admin/settings', {
method: 'POST',
headers: {
'Authorization': `Bearer ${await transcodes.token.getAccessToken()}`,
'X-MFA-Token': mfaToken,
},
body: JSON.stringify({ setting: 'value' }),
});
}Server-Side Verification
On your server, verify both the access token and MFA token:
// Node.js / Express
app.post('/api/admin/settings', async (req, res) => {
// 1. Verify access token (user is logged in)
const accessToken = req.headers.authorization?.split(' ')[1];
const user = await verifyAccessToken(accessToken);
if (!user) {
return res.status(401).json({ error: 'Unauthorized' });
}
// 2. Verify MFA token (user completed MFA)
const mfaToken = req.headers['x-mfa-token'];
const mfaValid = await verifyMfaToken(mfaToken);
if (!mfaValid) {
return res.status(403).json({ error: 'MFA verification required' });
}
// 3. Proceed with sensitive action
await updateSettings(req.body);
res.json({ success: true });
});MFA Session Caching
To avoid requiring MFA on every action, you can cache the MFA verification:
class MfaManager {
constructor() {
this.mfaVerifiedAt = null;
this.mfaValidDuration = 15 * 60 * 1000; // 15 minutes
}
async requireMfa() {
// Check if MFA was recently verified
if (this.isMfaValid()) {
return true;
}
// Prompt for MFA
const result = await transcodes.openAuthMfaModal();
if (result.success) {
this.mfaVerifiedAt = Date.now();
return true;
}
return false;
}
isMfaValid() {
if (!this.mfaVerifiedAt) return false;
const elapsed = Date.now() - this.mfaVerifiedAt;
return elapsed < this.mfaValidDuration;
}
clearMfa() {
this.mfaVerifiedAt = null;
}
}
// Usage
const mfaManager = new MfaManager();
async function accessAdminPanel() {
if (await mfaManager.requireMfa()) {
// MFA valid - proceed
showAdminPanel();
}
}Best Practices
Security Recommendations:
- Always verify MFA server-side - Donβt trust client-side MFA alone
- Set reasonable MFA session duration - 15-30 minutes is typical
- Clear MFA on logout - Reset MFA cache when user logs out
- Log MFA events - Track when MFA is used for audit purposes
Handle User Without MFA
If a user hasnβt set up MFA yet:
const mfaResult = await transcodes.openAuthMfaModal();
if (!mfaResult.success) {
// Check if user has MFA set up
const hasMfa = await transcodes.user.hasMfaEnabled();
if (!hasMfa) {
// Redirect to MFA setup
alert('Please set up MFA first');
await transcodes.openAuthModal(); // Opens console panel for MFA setup
}
}Congratulations!
π Youβve successfully integrated Step-up MFA into your application!
No server-side verification is needed for MFA β the verification is handled entirely by Transcodes.
Last updated on