WEB / WEB-14.04
Trust assumptions behind MFA
Two screens or two secrets do not necessarily mean two independent factors. Follow the MFA decision through challenges, account binding, and assurance state.
1. Core · Mechanism
Read every scenario without motion
Independent factor accepted
- First factor complete; MFA pending
The Application receives a verified first-factor result for this attempt. The Browser has neither completed MFA context nor a sensitive-action result yet; acceptance conditions for the second factor remain pending.
- Browser / Duru
- No completed MFA context
- Application verifier
- Primary verified; MFA pending
- Factor and challenge records
- Enrolled factor bound to subject-duru
- Pending challenge created
Within the same process, the Application binds challenge-ledger-a to attempt-duru-a, subject-duru, factorRef and purpose=mfa-login. Creating a pending record does not complete MFA; the Browser has not received the prompt either.
- Browser / Duru
- No completed MFA context
- Application verifier
- Challenge issued
- Factor and challenge records
- challenge-ledger-a: pending
- Challenge prompt reached the Browser
The response contains a challenge alias/prompt, not OTP output.
- Browser / Duru
- Prompt for challenge-ledger-a
- Application verifier
- Waiting for completion
- Factor and challenge records
- challenge-ledger-a: pending
- Factor input prepared
Enrolled-device output is represented by an alias; this step is local in the Browser with no actual device wire.
- Browser / Duru
- Output alias ready
- Application verifier
- Waiting for completion
- Factor and challenge records
- challenge-ledger-a: pending
- Completion request arrived
The completion request reached the Application with its output alias and attempt reference. While the Browser waits, the verifier will evaluate this attempt’s pending record and account binding; request arrival alone is not MFA acceptance.
- Browser / Duru
- Waiting for final decision
- Application verifier
- Completion received; not accepted yet
- Factor and challenge records
- challenge-ledger-a: pending
- Verification and lifecycle gate
For this attempt, firstFactorVerified, distinctFactors, factorBoundToSubject, purposeMatches, outputMatches, unused, withinLifetime and attemptAllowed are all true. The Application consumes the pending challenge once: afterState=consumed and mfaEstablished=true. The Browser has not received the result yet.
- Browser / Duru
- Waiting for final decision
- Application verifier
- Accepted: challenge consumed
- Factor and challenge records
- challenge-ledger-a: consumed
- Terminal decision at the Browser
The Browser received the completed MFA-context result. It belongs only to attempt-duru-a and mfa-login; session-cookie issuance and sensitive-action object/action permission are evaluated separately.
- Browser / Duru
- MFA context complete
- Application verifier
- Accepted: challenge consumed
- Factor and challenge records
- challenge-ledger-a: consumed
Lifetime expired
- First factor complete; MFA pending
The Application receives a verified first-factor result for this attempt. The Browser has neither completed MFA context nor a sensitive-action result yet; acceptance conditions for the second factor remain pending.
- Browser / Duru
- No completed MFA context
- Application verifier
- Primary verified; MFA pending
- Factor and challenge records
- Enrolled factor bound to subject-duru
- Pending challenge created
Within the same process, the Application binds challenge-ledger-a to attempt-duru-a, subject-duru, factorRef and purpose=mfa-login. Creating a pending record does not complete MFA; the Browser has not received the prompt either.
- Browser / Duru
- No completed MFA context
- Application verifier
- Challenge issued
- Factor and challenge records
- challenge-ledger-a: pending
- Challenge prompt reached the Browser
The response contains a challenge alias/prompt, not OTP output.
- Browser / Duru
- Prompt for challenge-ledger-a
- Application verifier
- Waiting for completion
- Factor and challenge records
- challenge-ledger-a: pending
- Factor input prepared
Enrolled-device output is represented by an alias; this step is local in the Browser with no actual device wire.
- Browser / Duru
- Output alias ready
- Application verifier
- Waiting for completion
- Factor and challenge records
- challenge-ledger-a: pending
- Completion request arrived
The completion request reached the Application with its output alias and attempt reference. While the Browser waits, the verifier will evaluate this attempt’s pending record and account binding; request arrival alone is not MFA acceptance.
- Browser / Duru
- Waiting for final decision
- Application verifier
- Completion received; not accepted yet
- Factor and challenge records
- challenge-ledger-a: pending
- Verification and lifecycle gate
Although the output predicate passes, withinLifetime=false. The Application does not extend the challenge: afterState=expired and mfaEstablished=false remain. Other positive predicates cannot compensate for the lifetime boundary; completed assurance is withheld.
- Browser / Duru
- Waiting for final decision
- Application verifier
- Denied: lifetime expired
- Factor and challenge records
- challenge-ledger-a: expired
- Terminal decision at the Browser
The Browser received rejection for lifetime expiry. No completed MFA context or sensitive-action result was delivered; a matching output does not reopen this expired challenge. A new challenge must follow its own policy.
- Browser / Duru
- No completed MFA context
- Application verifier
- Denied: lifetime expired
- Factor and challenge records
- challenge-ledger-a: expired
Same factor · deny
- First factor complete; MFA pending
The Application receives a verified first-factor result for this attempt. The Browser has neither completed MFA context nor a sensitive-action result yet; acceptance conditions for the second factor remain pending.
- Browser / Duru
- No completed MFA context
- Application verifier
- Primary verified; MFA pending
- Factor and challenge records
- Enrolled factor bound to subject-duru
- Pending challenge created
Within the same process, the Application binds challenge-ledger-a to attempt-duru-a, subject-duru, factorRef and purpose=mfa-login. Creating a pending record does not complete MFA; the Browser has not received the prompt either.
- Browser / Duru
- No completed MFA context
- Application verifier
- Challenge issued
- Factor and challenge records
- challenge-ledger-a: pending
- Challenge prompt reached the Browser
The response contains a challenge alias/prompt, not OTP output.
- Browser / Duru
- Prompt for challenge-ledger-a
- Application verifier
- Waiting for completion
- Factor and challenge records
- challenge-ledger-a: pending
- Factor input prepared
A second knowledge input is prepared as an alias; it does not create a distinct possession-factor result.
- Browser / Duru
- Knowledge response alias ready
- Application verifier
- Waiting for completion
- Factor and challenge records
- challenge-ledger-a: pending
- Completion request arrived
The completion request reached the Application with its output alias and attempt reference. While the Browser waits, the verifier will evaluate this attempt’s pending record and account binding; request arrival alone is not MFA acceptance.
- Browser / Duru
- Waiting for final decision
- Application verifier
- Completion received; not accepted yet
- Factor and challenge records
- challenge-ledger-a: pending
- Verification and lifecycle gate
The first and second factors are both knowledge, so distinctFactors=false. Even with outputMatches=true, the Application does not accept two knowledge results as MFA: afterState=rejected and mfaEstablished=false remain.
- Browser / Duru
- Waiting for final decision
- Application verifier
- Denied: same factor category
- Factor and challenge records
- challenge-ledger-a: rejected
- Terminal decision at the Browser
The Browser received rejection for the repeated factor category. No completed MFA context or sensitive-action result was delivered; two successful knowledge prompts do not supply the required knowledge-plus-possession composition.
- Browser / Duru
- No completed MFA context
- Application verifier
- Denied: same factor category
- Factor and challenge records
- challenge-ledger-a: rejected
ACTORS · STATE · DATA FLOW
Duru passed the password check; authentication is not complete
Atlas receives Duru’s password result for an action requiring another factor. The verified subject from WEB-14.01 is the first-stage input. The Application does not set mfaComplete=true yet: it must verify that another authenticator is bound to this account and produced the required result for this attempt.
The normal fixture follows authAttempt=attempt-duru-a, subject=subject-duru, and factorRef=otp-device-a. These are correlation aliases. A pending challenge withholds the sensitive action; passing the password stage does not deliver the second-stage protected capability to the Browser.
Factor count is not prompt count
Knowledge, possession, and inherence are different factor types. A password followed by another password or centrally checked PIN repeats the knowledge category. Password plus proof of authenticator possession can use different categories. Correct binding to the same account and resistance to replacement through one weak recovery path remain separate requirements.
A single authenticator can be multi-factor: a device PIN or biometric activation can unlock use of its private key. The activation secret need not be sent to the server as another password. Biometrics alone are not an authenticator under the NIST model; their relationship to a physical authenticator matters. Location and IP reputation are risk signals rather than substitutes for factors.
Challenge lifecycle: issue, verify, consume
The Application associates challenge-ledger-a with an attempt, subject, factor, and purpose=mfa-login. The alias returned to the Browser is not an OTP; enrolled-authenticator output is represented only by OTP_RESPONSE_ALIAS. OutputMatches=true is a supplied input standing for a trusted verification result.
Acceptance is a conjunction: firstFactorVerified, distinctFactors, factorBoundToSubject, purposeMatches, outputMatches, unused, withinLifetime, and attemptAllowed must all be true. Acceptance consumes the challenge and completes assurance for that attempt. Atomic consumption prevents concurrent completions from independently using the same pending record; storage may be in process or shared.
In the expired branch, an apparently correct output does not change withinLifetime=false. In the same-factor branch, outputMatches=true cannot overcome distinctFactors=false. These outcomes explain independent acceptance conditions rather than secret-guessing success.
OTP, push, and WebAuthn protect different phishing boundaries
MFA can reduce the effect of password disclosure without making every MFA protocol phishing-resistant. NIST uses that term for a protocol property that prevents valid authenticator output reaching an impostor verifier without depending on user vigilance. Manual OTP entry lacks that verifier binding; WebAuthn can provide verifier name binding.
Push approval depends on user intent and the request being approved. Rate limits, clear context, and number matching can reduce mistaken approval; a push screen alone does not establish WebAuthn-style cryptographic origin binding. This lesson models OTP lifecycle, not push delivery, WebAuthn signatures, or measured AAL compliance.
Phishing-resistant authentication does not automatically secure subsequent session use or correct resource permissions. WEB-13.03 completes the session lifecycle, while WEB-14.S02 develops recovery and credential-association boundaries.
2. Red · Trust & Impact
Read every scenario without motion
Same factor type
- The attempt context was separated
subject-duru, attempt-duru-a and challenge-ledger-a define this decision scope. The response alias is not an actual OTP code; output matching does not establish a global MFA flag.
- Attempt context
- case=same-factor
- Factor gate
- Factor not evaluated
- Assurance decision
- MFA not established
- The first-factor outcome was preserved
firstFactorVerified=true is supplied. The primary factor is knowledge; this one outcome does not complete all authentication-assurance conditions.
- Attempt context
- case=same-factor
- Factor gate
- Primary knowledge verified
- Assurance decision
- MFA not established
- The second-factor gate was read
A knowledge secondary factor gives distinctFactors=false. Two knowledge challenges do not become an independent knowledge-plus-possession pair under this policy.
- Attempt context
- case=same-factor
- Factor gate
- distinctFactors=false
- Assurance decision
- MFA not established
- Binding conditions were kept separate
True subject, purpose, output, unused and attemptAllowed predicates do not compensate for failed distinctFactors. The conditions remain bound to the same attempt.
- Attempt context
- case=same-factor
- Factor gate
- Failed gate retained
- Assurance decision
- MFA not established
- Assurance was not elevated
mfaEstablished=false and afterState=rejected remain. A completed label in the browser cannot change this server decision.
- Attempt context
- case=same-factor
- Factor gate
- afterState=rejected
- Assurance decision
- mfaEstablished=false
- The rejection reason was not broadened
Rejecting the same factor type does not make knowledge invalid for every use; this MFA-composition condition was not satisfied.
- Attempt context
- case=same-factor
- Factor gate
- Composition denial
- Assurance decision
- No elevated assurance
Expired challenge
- The attempt context was separated
subject-duru, attempt-duru-a and challenge-ledger-a define this decision scope. The response alias is not an actual OTP code; output matching does not establish a global MFA flag.
- Attempt context
- case=expired
- Factor gate
- Factor not evaluated
- Assurance decision
- MFA not established
- The first-factor outcome was preserved
firstFactorVerified=true is supplied. The primary factor is knowledge; this one outcome does not complete all authentication-assurance conditions.
- Attempt context
- case=expired
- Factor gate
- Primary knowledge verified
- Assurance decision
- MFA not established
- The second-factor gate was read
The secondary factor is possession with distinctFactors=true, but withinLifetime=false. A correct output does not extend an expired challenge.
- Attempt context
- case=expired
- Factor gate
- withinLifetime=false
- Assurance decision
- MFA not established
- Binding conditions were kept separate
True subject, purpose, output, unused and attemptAllowed predicates do not compensate for failed withinLifetime. The conditions remain bound to the same attempt.
- Attempt context
- case=expired
- Factor gate
- Failed gate retained
- Assurance decision
- MFA not established
- Assurance was not elevated
mfaEstablished=false and afterState=expired remain. A completed label in the browser cannot change this server decision.
- Attempt context
- case=expired
- Factor gate
- afterState=expired
- Assurance decision
- mfaEstablished=false
- The rejection reason was not broadened
An expired response can result from a benign delay. This reason is not evidence of a malicious actor; new challenges and recovery follow their own policies.
- Attempt context
- case=expired
- Factor gate
- Lifetime denial
- Assurance decision
- No elevated assurance
ASSUMPTION · BOUNDARY · CONTROL
A verified output cannot authorize the wrong attempt
Normal operation binds enrolled-authenticator output to Duru’s pending attempt. Turning an isolated “output correct” boolean into a global MFA flag loses subject, purpose, and lifecycle relationships. The potential effect is elevated assurance assigned to an incorrect or stale context.
The blocking control evaluates the pending attempt record alongside trusted account binding and lifetime. A challenge reference and decision reason can explain the result without logging the output. A completed label in the Browser cannot replace the server decision.
Independence must survive recovery and fallback
The benefit of multiple factors does not depend only on normal-login prompts. If factor replacement or an alternative API skips the assurance gate, authenticated state can be established under that weaker path’s conditions. Scope is the affected account and granted session/action authority, not automatic access to every resource.
Make fallback an explicit policy with an allowed method, required proof, and limited recovery capability. Support users who lose a factor without removing an enrolled factor solely because a session exists. Normal use, device migration, and incident recovery are different cases.
3. Blue · Secure development & defense
Read every scenario without motion
Assurance record
- The assurance-audit scope was selected
An audit example produced by the Application’s normal decision was selected. This review covers the selector’s distinctFactors, lifetimeValid, purposeMatched and challengeState fields; it contains no actual authenticator output.
- Assurance audit
- normal assurance: full record
- Challenge review
- Audit not examined
- Integrity conclusion
- No integrity conclusion
- Attempt and purpose were correlated
mfaEstablished=true belongs to attempt-duru-a and purpose mfa-login. This assurance is not automatically carried as permission for another action or account.
- Assurance audit
- normal assurance: full record
- Challenge review
- Purpose matched; attempt scope
- Integrity conclusion
- No integrity conclusion
- Factor independence was read
The normal branch uses knowledge plus possession with distinctFactors=true. Review compares factor type and account binding rather than merely counting successful prompts.
- Assurance audit
- normal assurance: full record
- Challenge review
- Distinct factors=true
- Integrity conclusion
- No integrity conclusion
- The terminal challenge outcome was separated
challengeState=consumed records the one-time decision for this attempt. Terminal state can be correlated without storing the output value in the audit.
- Assurance audit
- normal assurance: full record
- Challenge review
- Challenge consumed
- Integrity conclusion
- No integrity conclusion
- Lifetime evidence was sought
lifetimeValid=true is present in the full record, allowing the integrity predicate to be evaluated with distinctFactors and purpose.
- Assurance audit
- normal assurance: full record
- Challenge review
- Lifetime valid=true
- Integrity conclusion
- Complete predicate can be read
- The audit conclusion closed in scope
The main example has integrity count=0 for the four recorded conditions; a separate same-factor positive fixture gives count=1. This narrow result does not prove unrecorded output verification and account-binding checks or recovery adequacy.
- Assurance audit
- normal assurance: full record
- Challenge review
- Fixture integrity consistent
- Integrity conclusion
- Four selected conditions consistent
Missing lifetime
- The assurance-audit scope was selected
This branch examines fields other than lifetimeValid of the normal assurance record. Observation uses decision fields rather than actual authenticator output.
- Assurance audit
- normal assurance: lifetime omitted
- Challenge review
- Audit not examined
- Integrity conclusion
- No integrity conclusion
- Attempt and purpose were correlated
mfaEstablished=true belongs to attempt-duru-a and purpose mfa-login. This assurance is not automatically carried as permission for another action or account.
- Assurance audit
- normal assurance: lifetime omitted
- Challenge review
- Purpose matched; attempt scope
- Integrity conclusion
- No integrity conclusion
- Factor independence was read
The normal branch uses knowledge plus possession with distinctFactors=true. Review compares factor type and account binding rather than merely counting successful prompts.
- Assurance audit
- normal assurance: lifetime omitted
- Challenge review
- Distinct factors=true
- Integrity conclusion
- No integrity conclusion
- The terminal challenge outcome was separated
challengeState=consumed records the one-time decision for this attempt. Terminal state can be correlated without storing the output value in the audit.
- Assurance audit
- normal assurance: lifetime omitted
- Challenge review
- Challenge consumed
- Integrity conclusion
- No integrity conclusion
- Lifetime evidence was sought
lifetimeValid is not supplied in this review. Missing is not false; an empty selector result cannot prove the lifetime control passed.
- Assurance audit
- normal assurance: lifetime omitted
- Challenge review
- Lifetime evidence missing
- Integrity conclusion
- UNKNOWN: assurance integrity
- The audit conclusion closed in scope
This partial record does not support a clean assurance conclusion. Lifetime evidence must come from its trusted source; event absence is not promoted to actor attribution or MFA-failure evidence.
- Assurance audit
- normal assurance: lifetime omitted
- Challenge review
- Incomplete coverage
- Integrity conclusion
- UNKNOWN: lifetime gate
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Observe attempt, factor, and terminal outcome together
Sanitized audit emitted at the Application’s challenge issue/verify/consume decisions differs from observing a Browser prompt. attemptRef, subjectRef, factorType, purposeMatched, challengeState, lifetimeValid, and mfaEstablished belong to our instructional schema, not an existing product’s SIEM fields.
The artifact XPath checks four recorded conditions where mfaEstablished=true: distinctFactors, lifetimeValid, purposeMatched and challengeState=consumed. The main fixture contains no inconsistency among those fields and selects zero rows; a separate positive fixture with distinctFactors=false selects one. This count does not verify unrecorded checks such as output verification or account binding. Missing fields or events do not establish clean assurance, and the selector does not diagnose an account attack.
An accessible rollout and recovery inventory
Start policy changes with an account/factor inventory: enrolled methods, migration, accessibility needs, and fallback ownership must be understood. Lost devices, delayed output, and cancelled prompts are normal failures; rejection alone is not evidence of malice.
Compare the accepted, expired, and same-factor fixtures at the withholding/allow boundary. Established provider/library behavior, independent notification, and recovery need their own assessment in production; users need a way out of permanent lockout.
Make assurance elevation a server decision
Bind provider or library authenticator-verification results to the account’s enrolled factor and this authentication attempt. Two passwords are not two independent factors; the chosen assurance policy defines acceptable combinations. In this example, subject, purpose, lifetime and unused challenge state must pass before mfaEstablished is granted. Make challenge consumption and assurance elevation one consistent state transition; an unavailable verification service cannot be replaced by a successful-looking Browser prompt.
For an OTP flow, enforce a short lifetime, attempt limits and single use of successful output under the provider contract; acceptance must not leave reusable state. The normal accepted branch should establish assurance; expired and same-factor branches must withhold protected results. Missing account-binding or verifier-outcome evidence is not clean assurance. Design safe approval and notification for factor replacement and recovery independently of merely holding a session; timeout or reset must not silently reduce required authentication strength.
NOW APPLY IT TO THE CASE
Which attempt, factors and lifetime bind an MFA result?
MFA assurance depends on subject, purpose, distinct factors and challenge state as well as matching output. Missing audit fields are not a clean result.
Separate decisions for verified actor, tenant relation and requested action in the case. Do not substitute authentication or proof success for object permission.
Open the related case file ↗READ THE EXAMPLE TOGETHER
MFA challenge/result lifecycle
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"subject": "subject-duru",
"attemptRef": "attempt-duru-a",
"challengeRef": "challenge-ledger-a",
"responseAlias": "OTP_RESPONSE_ALIAS_NOT_A_CODE",
"primaryFactor": "knowledge",
"purpose": "mfa-login",
"rows": [
{
"case": "normal",
"firstFactorVerified": true,
"distinctFactors": true,
"factorBoundToSubject": true,
"purposeMatches": true,
"outputMatches": true,
"unused": true,
"withinLifetime": true,
"attemptAllowed": true,
"mfaEstablished": true,
"afterState": "consumed",
"secondaryFactor": "possession",
"factorRef": "otp-device-a",
"responseAlias": "OTP_RESPONSE_ALIAS_NOT_A_CODE"
},
{
"case": "expired",
"firstFactorVerified": true,
"distinctFactors": true,
"factorBoundToSubject": true,
"purposeMatches": true,
"outputMatches": true,
"unused": true,
"withinLifetime": false,
"attemptAllowed": true,
"mfaEstablished": false,
"afterState": "expired",
"secondaryFactor": "possession",
"factorRef": "otp-device-a",
"responseAlias": "OTP_RESPONSE_ALIAS_NOT_A_CODE"
},
{
"case": "same-factor",
"firstFactorVerified": true,
"distinctFactors": false,
"factorBoundToSubject": true,
"purposeMatches": true,
"outputMatches": true,
"unused": true,
"withinLifetime": true,
"attemptAllowed": true,
"mfaEstablished": false,
"afterState": "rejected",
"secondaryFactor": "knowledge",
"factorRef": "second-knowledge-factor-a",
"responseAlias": "KNOWLEDGE_RESPONSE_ALIAS_ONLY"
}
],
"selector": {
"language": "XPath",
"xml": "<audit><attempt mfaEstablished=\"true\" distinctFactors=\"true\" lifetimeValid=\"true\" purposeMatched=\"true\" challengeState=\"consumed\"/></audit>",
"xpath": "count(/audit/attempt[@mfaEstablished=\"true\" and (@distinctFactors=\"false\" or @lifetimeValid=\"false\" or @purposeMatched=\"false\" or @challengeState!=\"consumed\")])",
"expected": 0,
"positiveFixtureXml": "<audit><attempt mfaEstablished=\"true\" distinctFactors=\"false\" lifetimeValid=\"true\" purposeMatched=\"true\" challengeState=\"consumed\"/></audit>",
"positiveExpected": 1,
"scope": "Local assurance-integrity evidence only; no OTP/device verification or multi-host ordering.",
"missingFieldBehavior": "Selection requires declared fields. Missing fields mean insufficient evidence; a zero count does not prove control efficacy."
},
"normalSecondaryFactor": "possession"
}- attemptRef / subject / challengeRef
- Correlation aliases bind the decision to one attempt, account, and pending record.
- outputMatches / unused / withinLifetime
- Supplied verification and lifecycle predicates rather than output bytes or clock measurements.
- distinctFactors / mfaEstablished
- Repeating a factor category does not add a factor; completion requires every acceptance gate.
- selector
- Authored XML integrity selection; a missing field provides insufficient evidence.
Fixed aliases are not secrets. Cryptography, device output, email/push delivery, session issuance, and AAL compliance are not implemented; first-factor success and second-verification predicates are supplied inputs.
Two reality checks
Two password prompts automatically provide MFA.
Repeating knowledge does not create two independent factors; categories and account binding need separate checks.
Every OTP or push approval is phishing-resistant authentication.
MFA and phishing resistance are different properties; the protocol must provide verifier binding.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
A knowledge primary factor is followed by a verified second knowledge factor. Is selected MFA established?
- No; distinctFactors=false.
- Yes; any two successful prompts automatically constitute MFA.
Read the explained answer
No; distinctFactors=false. — In the same-factor row, outputMatches is true but the required factor-diversity gate fails.
Does a matching output complete an expired challenge?
Selected lesson artifact fields; teaching example
- rows[1].outputMatches
- true
- rows[1].withinLifetime
- false
- rows[1].mfaEstablished
- false
- rows[1].afterState
- expired
- Yes; lifetime policy is irrelevant when the response matches.
- No; an expired challenge produces no MFA context.
Read the explained answer
No; an expired challenge produces no MFA context. — WithinLifetime=false closes the gate despite the other true conditions; afterState is expired.
The normal possession challenge was consumed. Why does this establish neither phishing resistance nor permission for every sensitive action?
Read the explained answer
The selected fixture establishes MFA context using knowledge+possession and lifetime/purpose checks; it executes no actual OTP/device verification. An OTP-style factor alone is not proof of verifier-name binding or a phishing-resistant protocol. Completed MFA assurance does not automatically grant user/object/action authorization or action-specific reauthentication policy.
□ I separated MFA context from phishing resistance.
□ I did not count completed MFA as a blanket action grant.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
Sources and scope
- NIST SP 800-63B-4 — Authentication and Authenticator Management2.2 Authentication Assurance Level 2 · 3.1.1.2 Password Verifiers · 3.2.2 Rate Limiting (Throttling) · 3.2.5 Phishing Resistance · 4.1 Authenticator Binding · 4.2 Account Recovery · 4.5 Invalidation · 4.6 Account Notifications
- OWASP — Multifactor Authentication Cheat SheetIntroduction · One-Time Password (OTP) Handling and Storage · Resetting MFA · Changing MFA Factors · MFA Fatigue (Push Notification Bombing): Mitigations
- OWASP — Logging Cheat SheetWhich events to log · Event attributes · Data to exclude · Verification