Agent Wranglers

Recommended

Tell people when their password worked but the second factor failed

When a sign-in passes the password but fails the second factor, offer another factor and notify the account owner. Show the attempt at their next sign-in too.

Applies when

The project has user accounts.

How to do it

A correct password followed by a failed factor means the person lost the factor or someone else knows the password. The OWASP Multifactor Authentication Cheat Sheet asks for three steps. Offer another bound factor or a recovery code. Offer a reset of the factor. Tell the owner, with the time, browser and approximate place. Send that notice as tell people about every change to their sign-in sends its notices. Add a link to change the password. Send one notice per sign-in attempt, not one per wrong code. Count the wrong codes as offer two-factor login says.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

JavaScript example

export async function onSecondFactorAbandoned(attempt) {
  if (!attempt.passwordOk || attempt.secondFactorOk || attempt.noticeSent) return;
  await securityLog.append({ userId: attempt.userId, type: 'second_factor.failed', device: attempt.deviceLabel, place: attempt.place });
  await mailer.sendSecurityNotice(attempt.userId, { type: 'second_factor.failed', at: attempt.startedAt, device: attempt.deviceLabel, place: attempt.place });
  await attempts.markNoticeSent(attempt.id);
}

Python example

def on_second_factor_abandoned(attempt) -> None:
    if not attempt.password_ok or attempt.second_factor_ok or attempt.notice_sent:
        return
    event = {"type": "second_factor.failed", "at": attempt.started_at, "device": attempt.device_label, "place": attempt.place}
    security_log.append(user_id=attempt.user_id, **event)
    mailer.send_security_notice(attempt.user_id, event)
    attempts.mark_notice_sent(attempt.id)

How to check

On staging, enter a test user's correct password, then three wrong codes, then leave. One notice arrives with the time and browser. The next sign-in shows the failed attempt. The code page links to another factor and to a recovery code.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/accounts/second-factors-and-recovery/failed-second-factor">Agent Wranglers accounts playbook</a>. In code you write, add a comment next to it with the same link.