Verifying the User Verification Flag
The difference between a ceremony where somebody touched a device and one where the authenticator recognised the enrolled person is a single bit, and enforcing it is a server-side check that most implementations request and then forget to read. This page covers where the requirement can be lost, how to check it correctly, and how to carry the result into the session so later decisions do not have to guess. It sits under Implementing Authentication Verification Logic.
Flag Reference
| Setting | Client behaviour | Server obligation |
|---|---|---|
discouraged |
avoid verification where possible | check the bit if any policy depends on it |
preferred |
verify if the authenticator can | check the bit; expect it to be clear sometimes |
required |
fail the ceremony if verification is impossible | check the bit anyway |
The right-hand column does not vary. Whatever you request, the authority is the bit in authenticatorData.
Root Cause Analysis
1. Requesting and not checking. The most common shape. The options say required, nobody reads the flag, and the assumption is that the client enforced it. Clients generally do, but a server that does not verify is trusting a client-side control for a server-side decision.
2. Checking the wrong bit. The presence bit is set in essentially every ceremony. A policy that tests it always passes and enforces nothing, and the mistake is invisible in review because a hexadecimal mask looks equally plausible whichever bit it names.
3. Not carrying the result forward. The ceremony knows whether a human was verified; the session frequently does not. Every later decision then either re-runs a ceremony unnecessarily or assumes an answer it cannot see.
4. Requiring verification everywhere. Setting required on every ceremony excludes authenticators that cannot verify a user and interrupts people who are doing something harmless. The requirement belongs on the actions that need it.
Step-by-Step Resolution
Step 1 — decide where verification is actually required
Money movement, changes to security settings, credential management and account deletion. Reading data is not on the list.
Step 2 — request it for those ceremonies
Set the option to required for a step-up ceremony guarding one of those actions, and leave it at the default elsewhere.
Step 3 — read the bit from the decoded flags
Use a named boolean produced at the parse boundary, never an inline mask at the call site.
Step 4 — enforce at the point of decision
Compare the decoded value against the policy for the action being performed, and reject with a step-up requirement rather than a generic failure when it is not satisfied.
Step 5 — record it in the session
Store the result alongside the authentication time so a later request can answer the question without another ceremony.
Verification and Testing
A virtual authenticator configured without user verification is the cleanest test: a ceremony that requests required against it should fail at the client, and a ceremony that requests the default should succeed with the bit clear. Assert that your server rejects the second when the action requires verification.
Add a test that asserts the session claim. Complete a verified ceremony, then call a route that requires verification without a new ceremony, and assert that it passes on the strength of the recorded claim rather than prompting again.
Add the inverse: complete an unverified ceremony and assert that the same route demands a step-up.
Pitfalls
1. Trusting the request. The option is a preference expressed to the client; the bit is the fact.
2. Requiring verification on every ceremony. Produces prompt fatigue and excludes some authenticators.
3. Deriving policy from the authenticator model. Attestation tells you what a device can do, not what it did on this occasion.
Frequently Asked Questions
Does user verification count as a second factor?
In substance, yes: possession of the authenticator plus something the authenticator verified about the person. Whether it satisfies a specific regulatory definition of two-factor authentication depends on that regulation’s wording, and the honest position in a compliance discussion is to describe what the flag proves rather than to claim a label.
What if an authenticator cannot verify a user at all?
Then a ceremony requesting required will fail on that device. Some older security keys have no PIN and no biometric, and users of those keys need an alternative path for verified actions — which is a reason to require verification only where it matters rather than everywhere.
Should the flag change what the session can do, or whether it exists?
What it can do. Issuing no session because verification was absent turns a policy into a lockout; issuing a session at a reduced level and requiring a step-up for sensitive actions is both safer and kinder, and it keeps the audit trail honest about what was proved when.
How long should a verified state remain valid?
Long enough that a user completing a multi-step task is not interrupted repeatedly, and short enough that an abandoned session does not carry the assurance indefinitely. A few minutes is typical for a high-value action, and the comparison should be against the recorded authentication time rather than against session age.
Does the bit mean the same thing during registration?
Yes — authenticatorData has the same layout, and the flag reports whether the user was verified during the registration ceremony. Recording it at enrolment is useful, because a credential enrolled without verification tells you something about the authenticator’s capabilities.
Can a client lie about the flag?
The flag is inside authenticatorData, which is covered by the signature, so it cannot be altered after the authenticator produced it. What a client controls is whether it attempts verification at all — which is exactly why the server must read the result rather than trust the request.
How should the requirement be expressed in code?
As a property of the action rather than of the route. A table mapping action identifiers to their assurance requirements — verification needed, maximum age of the ceremony — read by one middleware, is far easier to audit than a scattering of conditionals in individual handlers. It also makes the requirement visible in one place when somebody asks which operations demand a verified user, which is a question that comes up in every security review and is otherwise answered by grepping.
Keeping the table adjacent to the routing configuration also makes the policy diffable: a change that relaxes a requirement shows up as an edit to a data file rather than as a one-character change buried in a handler, which is exactly the kind of change that deserves a second reader.
What should the response look like when the requirement is not met?
A specific status that the client can act on, carrying a fresh challenge for a step-up ceremony, rather than a generic failure. The distinction matters because the two produce completely different front-end behaviour: a generic error sends the user back to sign-in, while a step-up response lets the page run one more ceremony and retry the original request. Naming the requirement in the response is also what lets the interface explain the interruption in terms the user recognises.
Related
- Implementing Authentication Verification Logic — the parent topic area and the full check order
- Understanding the WebAuthn Flags Byte — where the bit lives
- Step-Up Authentication with Passkeys — acting on an unsatisfied requirement
- Issuing JWT Sessions After a WebAuthn Assertion — carrying the result into the session