Skip to content

MFA Chaining Strategies — Multi-Factor Authentication Chaining Patterns

DodaTech Updated 2026-06-28 1 min read

In this tutorial, you'll learn about Mfa Chaining. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

MFA chaining combines multiple authentication factors in sequence, with the second factor triggered by risk or sensitivity.

// Step-up MFA middleware
async function requireStepUpMFA(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];
  const decoded = jwt.decode(token);

  // Check if user has MFA verified in current session
  if (!decoded.amr?.includes('mfa')) {
    try {
      // Issue temporary token for MFA enrollment
      const mfaToken = jwt.sign(
        { sub: decoded.sub, purpose: 'mfa_stepup' },
        process.env.JWT_MFA_SECRET,
        { expiresIn: '5m' }
      );
      return res.status(403).json({
        error: 'mfa_required',
        mfa_url: `/auth/mfa/verify?token=${mfaToken}`,
        message: 'MFA verification required for this action'
      });
    } catch (err) {
      return res.status(500).json({ error: 'MFA step-up failed' });
    }
  }
  next();
}

// Risk-based MFA triggers
async function shouldRequireMFA(req, user) {
  const riskScore = 0;
  if (req.ip !== user.lastKnownIP) riskScore += 30;
  if (req.headers['user-agent'] !== user.lastUserAgent) riskScore += 20;
  if (Date.now() - user.lastLogin > 30 * 24 * 60 * 60 * 1000) riskScore += 25;
  if (req.geo?.country !== user.homeCountry) riskScore += 25;

  return riskScore >= 50;
}

// Route with MFA chaining
app.post('/api/scans/deep', requireAuth, async (req, res) => {
  const shouldMFA = await shouldRequireMFA(req, req.user);
  if (shouldMFA) return await requireStepUpMFA(req, res, () => {});
  // proceed with deep scan
});

MFA chaining applies stronger authentication only when necessary, balancing security with user experience.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro