Skip to Content
DocumentationDemonstrationStep-up AuthStep 4: Handle the MFA response

Step 4: Handle the MFA response

⏱ 5 min

Process the MFA verification result and implement your security logic


MFA Response Structure

interface IdpAuthResponse { success: boolean; sid?: string; // Step-up Session ID (on success) error?: string; // Error message (on failure) timestamp: number; // Unix timestamp in milliseconds action?: string; // Requested action type }

Basic Handling

const mfaResult = await transcodes.openAuthIdpModal({ resource: 'sensitive_action', action: 'delete', }); if (mfaResult.success && mfaResult.payload[0]?.success) { const { sid, timestamp } = mfaResult.payload[0]; console.log(`Verified at ${new Date(timestamp)}`); if (sid) console.log('Step-up Session ID:', sid); // 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 the access token to send to your server:

const mfaResult = await transcodes.openAuthIdpModal({ resource: 'admin_settings', action: 'update', }); if (mfaResult.success && mfaResult.payload[0]?.success) { // Get the access token const token = await transcodes.token.getAccessToken(); // Send to your server with the protected request const response = await fetch('/api/admin/settings', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ setting: 'value' }), }); }

Server-Side Verification

On your server, verify the access token (which proves the user completed MFA). For full JWT verification setup, see Server-Side Integration:

// Node.js / Express app.post('/api/admin/settings', async (req, res) => { // Verify access token (user is logged in and completed MFA) const accessToken = req.headers.authorization?.split(' ')[1]; const user = await verifyAccessToken(accessToken); if (!user) { return res.status(401).json({ error: 'Unauthorized' }); } // 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.openAuthIdpModal({ resource: 'sensitive_action', action: 'read', }); if (result.success && result.payload[0]?.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:

  1. Always verify tokens server-side - Don’t trust client-side MFA alone
  2. Set reasonable MFA session duration - 15-30 minutes is typical
  3. Clear MFA on logout - Reset MFA cache when user logs out
  4. Log MFA events - Use trackUserAction() for audit purposes

History Log

Record MFA and sensitive actions for audit logs using trackUserAction(). Events appear in the Audit Logs panel

// MFA verification success if (mfaResult.success && mfaResult.payload[0]?.success) { await transcodes.trackUserAction({ tag: 'admin:access', severity: 'high', status: true, metadata: { action: 'read' }, }); } // Sensitive action with webhook alert await transcodes.trackUserAction( { tag: 'payment:transfer', severity: 'high', status: true, metadata: { amount: 1000 } }, { webhookNotification: true } );
trackUserAction tagTypical use (audit log)
admin:accessAdmin panel access
user:deleteAccount deletion
document:deleteDocument deletion
payment:transferFinancial transaction

These tags are for trackUserAction() only. For openAuthIdpModal(), use resource + action (RBAC)—see Modal API.

See Audit API for full trackUserAction reference


Handle account without MFA

If the signed-in member has not set up MFA yet:

const mfaResult = await transcodes.openAuthIdpModal({ resource: 'sensitive_action', action: 'delete', forceStepUp: true, }); if (!mfaResult.success || !mfaResult.payload[0]?.success) { // Redirect to MFA setup in console panel alert('Please set up MFA first'); await transcodes.openAuthConsoleModal(); // Opens console panel for MFA setup }

Congratulations!

🎉 You’ve successfully integrated Step-up MFA into your application!

Modal API for full openAuthIdpModal parameters

Last updated on