Security engineer validating WebAuthn backup eligibility and backup state flags in a synthetic passkey test harness

Validate WebAuthn Backup Eligibility and Backup State

Wed, Sep 23, 2026

A relying party sees a WebAuthn assertion with a different backup-state bit than the value stored after an earlier ceremony. The tempting response is to treat the change as evidence that a credential was copied, synchronization was enabled or disabled, or the user deliberately changed something. That interpretation is too strong.

WebAuthn Level 3 makes a narrower distinction. Backup Eligibility (BE) is a property chosen for the public-key credential source when it is created, and that property is permanent for that credential source. Backup State (BS) reports the credential's current backup state and may change over time. The two values therefore have different lifecycles and should not be collapsed into one “passkey is synced” field.

As of September 22, 2026, WebAuthn Level 3 is a W3C Recommendation dated August 25, 2026. Its authenticator-data layout assigns bit 3 to BE and bit 4 to BS, and its relying-party algorithms explicitly address their validation and storage.

The operational question for this article is therefore precise: before an RP changes authentication policy because a backup flag changed, can it prove that it parsed the flags correctly, preserved immutable backup eligibility, accepted only valid BE/BS combinations, distinguished a legitimate BS transition from a BE contradiction, and avoided state mutation when the ceremony failed?

The lab below is intentionally synthetic. It does not use, capture, import, or modify any real user's credential. It defines recorded authenticator-data fixtures and test-only state transitions so an engineering team can validate policy branches without turning assumptions about browser or platform behavior into WebAuthn requirements.

Scope and acceptance target

This article is about the two WebAuthn authenticator-data bits that describe credential backup characteristics and the relying-party decisions that follow from them. It deliberately does not become a generic passkey introduction, a platform comparison, or a survey of passwordless authentication.

That boundary matters because authenticator data is a protocol artifact. WebAuthn defines it as a byte array of at least 37 bytes: a 32-byte RP ID hash, a one-byte flags field, and a four-byte signature counter, followed by optional data. BE occupies bit 3 and BS bit 4.

The specification gives the key acceptance invariant: BE is fixed when the credential source is created and MUST NOT change, while BS may change according to the credential's current state. The combination BE=0, BS=1 is not allowed.

Scope item

In this article

Acceptance evidence

Decode BE and BS from authenticator data

Yes

Raw flag byte plus decoded Boolean values

Enforce valid BE/BS combinations

Yes

00, 10, 11 accepted structurally; 01 rejected

Preserve credential backup eligibility

Yes

Stored registration BE equals every later accepted assertion BE

Evaluate BS transitions

Yes

Explicit 0→1, 1→0, unchanged-state branches

Browser or operating-system comparison

No

No platform-specific conclusion required

Infer which backup/sync mechanism was used

No

No such inference enters policy

Infer user intent from BS

No

Policy records an observation, not an intent claim

Real credential testing

No

Synthetic fixtures only

This article deliberately does not repeat generic authentication selection, OAuth/JWT discussion, rate limiting, general API hardening, or broad deployment guidance already better suited to Building Secure and Scalable APIs. Its acceptance target is much narrower: an engineer should leave with testable RP rules for BE permanence, BS variability, invalid combinations, state persistence, and rollback.

Documented behavior versus engineering inference

A policy review becomes unreliable when normative WebAuthn requirements, implementation choices, experiments, and observations are written as though they have equal authority. They do not.

Documented behavior comes directly from the WebAuthn specification. The generating authenticator determines backup eligibility when the credential source is created; eligibility is permanent for that source. The current managing authenticator determines backup state, and that state may change over time. For a multi-device credential, the authenticator managing a later authentication can differ from the authenticator that originally generated the credential.

The specification also says backup can occur through multiple mechanisms, including peer-to-peer synchronization, cloud synchronization, local-network synchronization, or manual import/export. Therefore BS=1 does not tell an RP which mechanism was involved.

Evidence class

Example in this article

How to treat it

Documented behavior

BE is permanent; BS may change

Requirement or defined semantic from W3C

Engineering inference

Arrival-order writes can obscure the order in which different assertions were generated

Design risk derived from protocol/state behavior

Proposed experiment

Feed synthetic 0x09, 0x19, 0x11 flag bytes into the policy function

Test to run; not an observed result

Actual observation

The cited WebAuthn Level 3 Recommendation is dated August 25, 2026

Research fact checked for this article

A particularly important engineering inference concerns intent. WebAuthn says BS can transition from 1 to 0 because of user actions or errors associated with backup service behavior. It does not provide an intent bit. An RP may therefore react to the resilience consequence of BS=0, but should not label the event “user disabled sync” unless it has independent evidence for that conclusion.

Likewise, BS=1 should not be translated into “we proved this private key was copied to device X.” WebAuthn defines the observable state, while the specification explicitly allows different backup mechanisms. The defensible record is “authenticator reported BS=1 in this validated ceremony,” not an invented history of how or why the state arose.

That distinction should survive into incident notes, dashboards, and customer-facing text. It prevents an authenticator-provided status signal from acquiring more forensic certainty than the protocol gives it.

Lab fixture and version matrix

The primary lab should operate below the browser UX layer. A minimal authentication authenticatorData value is enough to test the flag decoder: 32 bytes of rpIdHash, one byte of flags, and four bytes of signCount. The W3C definition puts the flags byte at offset 32.

For assertions with UP set and UV omitted, four useful synthetic flag bytes are:

Fixture

Flags byte

BE

BS

Intended result

single_device

0x01

0

0

Structurally valid

eligible_not_backed_up

0x09

1

0

Structurally valid

eligible_backed_up

0x19

1

1

Structurally valid

invalid_bs_without_be

0x11

0

1

Reject

Those values follow directly from UP=0x01, BE=0x08, and BS=0x10. WebAuthn defines 00, 10, and 11 as valid BE/BS combinations and explicitly disallows 01.

A tiny fixture generator can keep this test deterministic:

import hashlib

UP = 0x01
BE = 0x08
BS = 0x10

RP_ID = "example.test"
RP_ID_HASH = hashlib.sha256(RP_ID.encode("utf-8")).digest()

def authenticator_data(flags: int, sign_count: int = 1) -> bytes:
    if not 0 <= flags <= 0xFF:
        raise ValueError("flags must fit in one byte")
    if not 0 <= sign_count <= 0xFFFFFFFF:
        raise ValueError("sign_count must fit in four bytes")
    return RP_ID_HASH + bytes([flags]) + sign_count.to_bytes(4, "big")

FIXTURES = {
    "single_device": authenticator_data(UP),
    "eligible_not_backed_up": authenticator_data(UP | BE),
    "eligible_backed_up": authenticator_data(UP | BE | BS),
    "invalid_bs_without_be": authenticator_data(UP | BS),
}

This code is a proposed fixture, not an executed test. It tests byte parsing and policy branching; it does not, by itself, prove that a complete WebAuthn assertion passed challenge, origin, RP ID hash, signature, UV, extension, or counter verification.

Version and environment matrix

Record versions even when the lab is intentionally small. As of September 22, 2026, Python.org lists CPython 3.14.7, released August 5, 2026, while Python 3.15 is still listed as a prerelease with October 1, 2026 planned.

Component

Proposed lab value

Why it is recorded

WebAuthn normative reference

W3C WebAuthn Level 3 Recommendation, August 25, 2026

Locks flag semantics to a published specification

Fixture interpreter

CPython 3.14.7

Makes byte-decoder reruns reproducible

RP ID

example.test

Synthetic/disposable namespace

Real user credentials

None

Required isolation boundary

Browser

None required for primary fixture test

Prevents browser behavior from becoming protocol evidence

OS dependency

None intended

Parser exercises raw bytes only

Fixture schema

backup-flags-v1

Lets evidence identify the test-data format

Optional WebDriver layer

Version recorded at execution time

Necessary only if virtual-authenticator testing is added

WebAuthn Level 3 also defines a WebDriver “Set Credential Properties” command that can alter backupEligibility and backupState on a virtual authenticator credential. The specification explicitly notes that backup eligibility is normally permanent but permits changing it through this command for testing and debugging. That makes a virtual authenticator appropriate for a secondary deliberate-failure lab, without asserting that a real conforming credential changes BE.

Baseline state and evidence model

The baseline needs two different stored values because WebAuthn gives them two different meanings. A credential record is recommended to contain backupEligible, defined as the BE value when the credential source was created, and backupState, defined as the latest BS value observed in authenticator data from a ceremony using that source.

At registration, the RP algorithm first rejects BS=1 when BE=0. It can then evaluate the flags for local policy, and the credential record created by the registration procedure stores the BE and BS values from that registration's authenticator data.

The baseline state model should therefore look like this:

Stored BE

Stored BS

Meaning at baseline

Permitted future observation

0

0

Single-device credential

BE must remain 0; BS must remain 0

1

0

Backup-eligible, not currently backed up

BE stays 1; BS may remain 0 or become 1

1

1

Backup-eligible and currently backed up

BE stays 1; BS may remain 1 or become 0

0

1

Invalid

Never create or accept this baseline

The useful conceptual state machine is therefore not four freely interchangeable states. It is:

BE=0, BS=0
     │
     └── BE cannot become 1 for this credential source

BE=1, BS=0  <──────────────>  BE=1, BS=1
             BS may change

BE=0, BS=1  = invalid

That model prevents a common schema mistake: updating both backupEligible and backupState on every successful login. The W3C credential-record definition treats backupEligible as the creation-time BE value, while backupState tracks the latest BS observation.

Engineering inference: make that semantic distinction visible in the database API. A field called backup_flags that is blindly replaced after every assertion makes it easier to overwrite immutable eligibility accidentally. Separate columns such as backup_eligible_at_registration and latest_backup_state communicate the lifecycle better, even though those exact database names are an application design choice rather than W3C terminology.

The baseline evidence package should contain the synthetic credential identifier, initial BE, initial BS, raw flags byte, fixture version, policy version, and expected decision. It should not contain a real credential ID, private key, or unrelated personal data.

Normal-path validation

The normal path begins by refusing to treat BE/BS as isolated business metadata. They are part of authenticator data, and an authentication assertion's signature is verified over the authenticator data concatenated with the hash of the client data.

WebAuthn's RP authentication algorithm first checks the normal ceremony conditions, including credential ownership, challenge, origin, RP ID hash, user presence, and any required user verification. It validates that BS is not set when BE is clear. When backup state participates in RP business logic or policy, it compares current BE with the credential record's stored backup eligibility and then applies RP policy. Signature verification follows in the normative algorithm.

For application architecture, the important persistence rule appears later: state updates occur only after the relevant verification steps, and if an RP performs additional security checks beyond the WebAuthn procedure, the specification says those state updates should be deferred until those checks succeed.

Incoming observation

Stored value

Normal-path decision

BE=0, BS=0

BE=0, BS=0

Continue after other ceremony checks

BE=1, BS=0

BE=1, BS=0

Continue; state unchanged

BE=1, BS=1

BE=1, BS=0

Continue if local BS policy allows; stage 0→1 update

BE=1, BS=0

BE=1, BS=1

Continue if local BS policy allows; stage 1→0 update

BE=0, BS=1

Any

Reject invalid combination

BE differs from stored BE

Any

Fail eligibility verification when backup-state policy is in use

A useful policy-function shape is:

parse authenticatorData
validate BE/BS structural combination
compare current BE with registration BE
classify current BS versus stored BS
apply explicit RP policy
complete cryptographic and additional security checks
commit latest BS only after successful completion

The exact execution graph can vary by WebAuthn library, but two semantics must survive the abstraction: a changed BS is possible; a changed BE for the same credential source contradicts the credential's stored eligibility.

A 0→1 BS transition means the authenticator is reporting that the credential is currently backed up. A 1→0 transition means the authenticator is reporting that it is no longer backed up and therefore is no longer protected from single-device loss. W3C recommends that an RP encountering the latter guide the user through validating other authentication factors and, where necessary, adding another credential.

None of those branches requires claiming that a particular cloud, device, export operation, or user choice caused the transition.

Boundary-condition experiment

The boundary lab should test both kinds of failure that production code often conflates: an impossible combination inside one authenticator-data value and an eligibility contradiction across ceremonies.

Use only synthetic credential records. A proposed baseline can be stored_BE=1, stored_BS=0. Feed the policy layer the following fixtures and record the decision without mutating the baseline until the full synthetic ceremony is considered successful.

Test

Stored BE/BS

Incoming BE/BS

Expected policy result

Stable eligible state

1/0

1/0

Accept branch

Legitimate state change

1/0

1/1

Accept branch; stage BS update

Return from backed up

1/1

1/0

Apply 1→0 resilience policy

Impossible combination

1/0

0/1

Reject before state update

Eligibility contradiction

1/0

0/0

Reject BE mismatch when policy comparison applies

Single-device baseline

0/0

0/0

Accept branch

Impossible single-device backup

0/0

0/1

Reject

WebAuthn directly supports the structural expectations: 0/1 is prohibited, BE must not change after credential creation, and RP verification compares current BE with stored eligibility when credential backup state is used in policy.

Deliberately failing boundary test

The most valuable deliberately failing test starts with a synthetic credential registered as BE=1, BS=0 and later supplies BE=0, BS=0 for that same credential identity.

This is not intended to simulate ordinary conforming behavior. It intentionally violates the BE permanence rule so the test can demonstrate that the RP refuses to silently “learn” a new eligibility value. WebAuthn's WebDriver extension is specifically capable of changing a virtual credential's backupEligibility for testing and debugging even though the property is normally permanent.

For a byte-only unit test, the proposed expected transcript is:

stored:   BE=1 BS=0
incoming: flags=0x01 -> BE=0 BS=0
result:   REJECT_BACKUP_ELIGIBILITY_MISMATCH
write:    none

For the independent malformed-state test:

incoming: flags=0x11 -> BE=0 BS=1
result:   REJECT_INVALID_BACKUP_FLAG_COMBINATION
write:    none

These are expected outputs of a proposed experiment, not observed outputs from an executed lab.

An especially dangerous implementation would instead produce:

stored before: BE=1 BS=0
incoming:      BE=0 BS=0
stored after:  BE=0 BS=0
result:        success

That would convert an invariant violation into apparently valid state. The RP would erase the very evidence needed to distinguish credential eligibility from current backup state, contrary to the Level 3 model in which stored backupEligible represents the creation-time BE value.

Recovery and rollback behavior

A failure is not fully tested merely because the next request succeeds.

Suppose the deliberately failing request reaches policy evaluation and is rejected for a BE mismatch. A subsequent request using the original valid fixture may return green. That green rerun proves only that the later request can succeed. It does not prove that the failed attempt left the database, cache, session, risk record, audit stream, or downstream account state untouched.

The WebAuthn RP algorithm reinforces the underlying principle by placing credential-state updates after verification and advising RPs to defer them until additional security checks have completed successfully.

Recovery artifact

State before failed attempt

Required state after failure

Stored backupEligible

1

1

Stored backupState

0

0

Authentication result

Not applicable

Failed

Pending policy mutation

None

None

Session elevation

None

None

User-facing recovery workflow

Not triggered unless policy explicitly calls for it

Deterministic

Audit event

No event yet

Failure event retained

Next valid request

Untested

May succeed, but does not erase failure evidence

A rollback test should therefore take a before-snapshot, issue the deliberately failing synthetic request, assert the rejection, and take an after-snapshot. Only then should it issue the clean rerun.

Engineering inference: transactional boundaries matter more than endpoint status codes here. If the RP updates backupState before signature verification, or writes an account-security change before a later policy check fails, a 401 or equivalent response may hide a partially committed mutation. The specification's deferral guidance is a strong reason to make persistence an explicit end-of-ceremony operation.

The same rule applies to rollback during deployment. Disabling the new policy branch should not mean deleting recorded observations. Roll back the decision logic while retaining enough versioned evidence to determine which rule evaluated each ceremony.

Concurrency, lifecycle, or version interaction

Backup state is mutable, but WebAuthn does not give an RP a globally ordered synchronization history for it.

For a multi-device credential, the generating authenticator may differ from the managing authenticator involved in a later authentication ceremony. The RP's credential-record abstraction describes backupState as the latest BS value from a ceremony using that credential source.

That creates an application-level concurrency problem. If two valid assertions are processed concurrently, “latest” can accidentally mean “last database commit” rather than “a trustworthy global chronology of backup operations.” WebAuthn's discussion of signature counters separately acknowledges that an RP can process assertion responses in a different order from the order in which authenticators generated them.

Interaction

Documented fact

Engineering treatment

Multi-device credential used by different managing authenticators

Permitted

Do not assume one device supplies every observation

BS differs between accepted ceremonies

BS may change

Record transition as an observation

Two requests race

Processing order can differ from generation order

Avoid claiming server commit order proves real-world transition order

BE differs

BE must be permanent

Treat as verification/invariant failure, not a normal race

Legacy implementation built around Level 2

Level 2 Recommendation predates Level 3 BE/BS model

Audit parser/schema before enabling Level 3 policy

WebDriver changes BE

Allowed for testing/debugging

Never interpret test mutation as normal credential behavior

WebAuthn Level 2 was published as a W3C Recommendation on April 8, 2021. Searches within that published Level 2 document do not contain the Level 3 “Backup Eligibility” or “backup state” terminology, while the August 25, 2026 Level 3 Recommendation defines BE/BS and the corresponding RP behavior.

That version distinction matters when upgrading an RP or library. An old schema may have no columns for backupEligible and backupState; an old parser may regard the formerly reserved flag positions differently; and an application may have policy assumptions written before these Level 3 semantics existed. Those are migration questions to test, not reasons to reinterpret the current specification.

A safe version-interaction test feeds the same recorded Level 3 fixtures through both the existing parser and the proposed parser, compares decoded flags, and blocks rollout if the two disagree unexpectedly. For broader API-versioning discipline, the same principle of making compatibility behavior explicit appears in Refonte Learning's API developer engineering guide.

Observability and evidence retention

The observability goal is not to collect everything. It is to preserve enough evidence to reproduce the RP's decision without turning authentication telemetry into an unnecessary archive of credential material.

A useful event records the policy inputs, policy version, decision, and mutation outcome. It should distinguish raw protocol observation from interpretation: observed_be=true is different from reason="credential copied", because the latter claim is not supplied by WebAuthn.

Evidence field

Retain?

Purpose

Ceremony correlation ID

Yes

Connect evaluation and persistence events

Synthetic fixture ID in lab

Yes

Make tests reproducible

Policy version

Yes

Explain which decision branch ran

Observed BE

Yes

Check immutable eligibility

Observed BS

Yes

Classify current state/transition

Previous stored BE/BS

Yes, where appropriate

Reconstruct comparison

Decision code

Yes

Distinguish malformed combination, BE mismatch, local BS policy

State-write outcome

Yes

Prove whether mutation occurred

Full private credential material

No

Not needed for this policy evidence

Assumed sync provider/device

No, unless independently known

BE/BS does not establish it

Assumed user intent

No

BS does not encode intent

Authenticator data derives its trust from the RP's assessment of the authenticator, and the data participates in the signed assertion. That makes it meaningful protocol evidence after verification, but it still does not expand the semantic meaning of BE or BS beyond what WebAuthn defines.

Data-retention design should also be reviewed through a privacy and minimization lens rather than assuming “security logging” justifies indefinite collection. Refonte's broader data-protection discussion across roles is a useful adjacent topic, while the WebAuthn-specific event here should stay focused on the minimum evidence necessary to reproduce the decision.

Evidence that must survive a rerun

A rerun must not overwrite the evidence for the request that failed. Give each attempt its own immutable correlation identifier and retain its result independently.

Artifact

Failed attempt

Clean rerun

Request/correlation ID

A

B

Fixture

BE mismatch

Valid baseline

Policy result

Reject

Expected success

Stored state before

Captured

Captured

Stored state after

Proved unchanged

Updated only if legitimate

Policy version

Recorded

Recorded

Audit entry

Retained

Separate entry

Evidence relationship

Original failure

Does not replace or “heal” A

This distinction is crucial to the deliberately failing test. A green B says nothing about whether A temporarily changed a cache, inserted a database row, generated a session, queued an account action, or emitted the wrong audit classification.

The acceptance evidence must instead show that A produced the intended failure and that all prohibited side effects remained absent. Only after that proof does the green rerun demonstrate recovery of the normal path.

Negative tests and false confidence

Positive tests are easy to overvalue in stateful authentication logic. Three valid fixtures can prove that three happy branches work while leaving the dangerous invariant failures untouched.

The strongest suite attacks each assumption separately. It also keeps cryptographic verification and policy interpretation conceptually separate: a byte-parser test can prove bit handling, whereas only an integrated synthetic assertion can prove that the RP applies the same decision to signed authenticator data after the rest of the ceremony checks.

Negative test

Failure it targets

What a green normal test cannot prove

BE=0, BS=1

Invalid flag combination accepted

That malformed states are rejected

Registration BE=1, assertion BE=0

Immutable value overwritten

That BE permanence is enforced

Registration BE=0, assertion BE=1

Same invariant in opposite direction

That comparison is symmetric

BS 1→0

State change ignored

That resilience branch executes

Bad signature plus plausible BE/BS

Trust in unverified flags

That policy effects wait for valid ceremony

Bad challenge/origin plus plausible flags

Partial verification

That valid flags cannot rescue an invalid assertion

Failed request followed by valid retry

Hidden partial write

That failure rollback actually worked

Two concurrent different-BS assertions

Arrival-order assumptions

That “latest” has valid ordering semantics

WebAuthn requires challenge, origin, RP ID hash, user-presence and relevant user-verification checks in addition to the BE/BS rules, and signature verification covers authenticator data and the client-data hash. A policy implementation that unit-tests only flags & 0x18 has therefore tested one component, not an authentication ceremony.

False confidence also appears when teams interpret one signal as proof of another. The WebAuthn specification itself is careful with signature-counter anomalies: a non-increasing counter can signal possible cloning, authenticator malfunction, or a request-processing race, and is explicitly described as a signal rather than proof. That is a useful discipline for backup-state telemetry too: record exactly what the protocol says before attaching a stronger causal story.

For teams formalizing these cases as regression tests, QA automation engineering is the adjacent discipline; the WebAuthn-specific requirement here is that deliberately broken behavior remains part of the suite rather than being replaced by happy-path coverage.

Operational rollout and rollback criteria

Do not turn on a new authentication consequence merely because a parser can expose two Boolean values.

Before rollout, inventory the credential-record schema, verify where BE and BS are written, identify whether existing records have trustworthy creation-time BE values, and determine what happens when historical data is absent. The W3C model recommends both backupEligible and backupState in the credential record, with different lifecycle definitions.

Rollout gate

Proceed when

Roll back or hold when

Parsing

BE/BS decoded from correct flag positions

Parser disagreement or unknown masking behavior

Data model

Immutable BE and mutable BS represented separately

One field conflates both concepts

Existing records

Migration provenance is understood

BE would need to be guessed

Invalid combination

0/1 deterministically fails

Request reaches policy success

BE mismatch

Deterministic failure/quarantine behavior defined

Code silently overwrites stored BE

BS transition

Explicit 0→1 and 1→0 branches exist

Generic “changed” handler loses direction

Persistence

Failed ceremony produces no forbidden state write

Any partial mutation occurs

Observability

Versioned decision evidence retained

Only generic login success/failure is visible

Rollback

Feature/policy branch can be disabled without deleting evidence

Rollback requires destructive data edits

For existing credentials where creation-time BE was never retained, do not manufacture history by copying the next observed BE into a field labeled “BE at registration” without marking its provenance. That next assertion can provide an observation, but it cannot retroactively prove what the RP actually stored at registration.

A practical migration can therefore distinguish records such as be_provenance=registration, be_provenance=first_level3_observation, and be_provenance=unknown. Those names are an engineering proposal, not a WebAuthn requirement, but they avoid making inferred migration data look like protocol evidence.

Rollout should also separate “observe” from “enforce.” An initial policy version can decode, validate structurally, and record transitions while leaving optional local consequences disabled; a later enforcement change can activate the decision branch after fixture, integration, rollback, and concurrency evidence has passed. That staged approach is consistent with the broader change-control discipline described in secure and scalable API engineering.

Treat the policy response as an API contract too. If downstream services consume a reason code such as BACKUP_STATE_CHANGED, document whether it means 0→1, 1→0, or either. The value of explicit machine-readable contracts is closely related to the concerns covered in Refonte's Swagger/OpenAPI article.

Acceptance matrix

The final acceptance test should combine protocol validity, stored state, transition direction, verification outcome, and persistence behavior.

The matrix below is intentionally stricter than “does login work?” because the proposed policy change concerns stateful security decisions. The WebAuthn foundations are that 0/1 is invalid, BE must remain constant, BS may change, and the RP's stored backup state is updated as part of successful processing rather than used as license to rewrite eligibility.

Stored BE

Stored BS

Current BE

Current BS

Other verification

Expected result

Persistent BS

0

0

0

0

Pass

Accept

0

0

0

0

1

Pass

Reject malformed flags

0

0

0

1

0

Pass

Reject BE contradiction

0

0

0

1

1

Pass

Reject BE contradiction

0

1

0

1

0

Pass

Accept

0

1

0

1

1

Pass

Accept/local 0→1 policy

1

1

1

1

1

Pass

Accept

1

1

1

1

0

Pass

Accept/local 1→0 policy

0

1

0

0

0

Pass

Reject BE contradiction

0

1

1

0

1

Pass

Reject malformed flags

1

1

0

1

1

Signature fails

Reject ceremony

0

1

0

1

1

Additional security check fails

Reject; no state update

0

Whether a valid 1→0 BS transition itself blocks authentication is an RP policy choice; WebAuthn instead describes the resilience implication and recommends guiding the user to validate other factors or add another credential when needed.

Pass criteria

The policy is ready only when the evidence demonstrates all of these conditions together:

Criterion

Required evidence

Correct bit decoding

Raw byte and expected BE/BS agree for every fixture

Structural validation

BE=0/BS=1 rejected

BE permanence

Both directions of BE mismatch rejected under the enabled policy

BS mutability

0→1 and 1→0 handled without rewriting BE

Full-verification boundary

Invalid signature/challenge/origin cannot trigger committed state

Failed-attempt cleanliness

Before/after state proves no forbidden mutation

Concurrency awareness

Test documents behavior under overlapping assertions

Reproducibility

Specification, runtime, fixture, and policy versions recorded

Evidence semantics

Logs state observation, not unsupported copy/intent claims

Rollback

Policy can be disabled without corrupting credential records

A pass does not require claiming that a particular browser, operating system, or credential provider will generate every transition in this matrix. The fixtures exist to validate the relying party's branch logic against WebAuthn semantics independently of those implementation-specific behaviors.

Hold, refactor, or quarantine conditions

The change should not reach enforcement if any of the following remains true:

Condition

Decision

Code overwrites stored BE on authentication

Refactor

BE and BS share one ambiguous state field

Refactor

BE=0/BS=1 reaches successful policy evaluation

Hold

Historical BE is unknown but treated as proven registration data

Hold

Failure can update BS before final acceptance

Refactor

BE mismatch appears in synthetic testing and code continues silently

Quarantine test path and fix policy

Production mismatch appears but evidence is insufficient

Quarantine decision; investigate without inventing cause

Log says “credential copied” solely because BS=1

Refactor telemetry semantics

Rollback destroys the original state/evidence

Hold

Test suite has no intentionally failing case

Hold

“Quarantine” here means separating an anomalous record or policy decision for investigation according to the RP's own operational design; it does not mean that WebAuthn defines a standardized quarantine mechanism.

Most importantly, an eligibility contradiction should not be normalized as a backup-state change. BE and BS answer different questions, and the entire acceptance model fails if the implementation treats them as interchangeable.

Common implementation mistakes

The recurring errors are mostly lifecycle errors rather than bitwise-programming errors. Reading bit 3 and bit 4 is straightforward; preserving their different semantics across registration, authentication, persistence, logging, migration, and policy changes is harder.

Mistake

Why it is wrong

Correction

Calling BE “current sync status”

BE is permanent eligibility

Store it as creation-time credential property

Treating BS as immutable

BS may change

Model explicit transitions

Accepting BE=0/BS=1

Combination is prohibited

Reject structurally

Updating BE after every assertion

Erases permanence invariant

Compare with stored BE; do not relearn it

Treating BS=1 as proof of a particular copying mechanism

WebAuthn allows multiple backup mechanisms

Record only backed-up state

Treating BS=0 as proof user disabled backup

Errors can also explain the state

Avoid unsupported intent claims

Writing BS before final checks

Failed request can leave stale state

Stage and commit after successful checks

Using successful rerun as cleanup proof

It says nothing about earlier side effects

Compare before/after evidence for failed attempt

Equating server arrival order with backup chronology

Concurrent assertions can be reordered

Treat each BS as a ceremony observation

Testing only browser UX

Confounds platform behavior with RP protocol logic

Keep raw synthetic fixture tests

Hiding policy in generic “risk score”

Makes acceptance hard to reproduce

Emit explicit reason codes and version

Migrating unknown legacy BE as fact

Invents registration history

Preserve provenance/unknown state

The specification itself gives RPs a useful model by recommending distinct backupEligible and backupState credential-record properties. It also distinguishes a fixed BE from a changing BS during assertion verification.

Another mistake is assuming that because the WebAuthn algorithm examines the backup-policy comparison before its signature-verification step, an application should commit business effects immediately. The same algorithm later updates state after the remaining verification steps and advises deferring updates further when additional security checks exist. Policy evaluation and durable mutation should therefore remain separate concerns.

For teams implementing this inside a broader API service, keep the WebAuthn-specific verification boundary explicit rather than burying it in generic middleware. Refonte's API developer engineering discussion provides the broader engineering context, but BE/BS correctness still needs its own protocol-level tests.

Final decision and Refonte Learning CTA

The policy change should be accepted only after the RP demonstrates, with synthetic evidence, that backup eligibility is treated as an immutable credential-source property while backup state is treated as a mutable observation.

That conclusion follows directly from WebAuthn Level 3. The generating authenticator determines eligibility at credential creation; BE must not change. BS reports current backup status and can change. 0/1 is invalid. An RP using backup state in policy compares the current BE with the stored eligibility and may then apply local policy to BS; successful processing updates stored backup state, while additional security checks should complete before those updates are committed.

The final operational rule can therefore be kept compact:

Observation

Final disposition

BE=0, BS=1

Reject as invalid

Current BE differs from proven registration BE

Fail invariant/policy verification; investigate

BS unchanged

Continue normal policy

BS 0→1

Record verified state observation; apply only documented local policy

BS 1→0

Record verified state observation; invoke resilience branch as appropriate

Ceremony fails after flags were parsed

Commit no prohibited credential-state change

Cause of BS transition unknown

Keep it unknown

Browser/platform behavior differs

Investigate implementation separately from WebAuthn semantics

This policy deliberately refuses a stronger conclusion than the available evidence supports. A backup-state flag is useful because it can drive resilience decisions; it becomes dangerous when the RP turns it into unsupported claims about credential copying, synchronization technology, device identity, or user intent. The WebAuthn definitions and backup mechanisms do not provide that level of causality.

Decision record

Decision-record field

Decision-record value

Normative baseline

W3C WebAuthn Level 3 Recommendation, August 25, 2026

Policy invariant

BE for an existing credential source does not change

Mutable state

BS may change between ceremonies

Structurally invalid state

BE=0, BS=1

Registration evidence

Persist creation-time BE and initial BS

Authentication evidence

Compare BE; classify BS transition; apply explicit RP policy

Test resource type

Synthetic authenticator-data fixtures or virtual authenticator only

Deliberate failure

Existing BE=1 credential observed with synthetic BE=0

Failure acceptance

Rejected with no forbidden persistent mutation

Recovery proof

Before/after evidence plus separate green rerun

Causal inference rule

Do not infer copying mechanism or user intent solely from BE/BS

Browser/platform conclusion

Outside primary acceptance target

Lab execution status

Proposed; no execution claimed in this article

The resulting engineering posture is intentionally conservative: trust the bits only after the surrounding WebAuthn verification succeeds, interpret them only according to their specified semantics, preserve the creation-time eligibility invariant, and make every policy consequence independently testable. That is enough to turn “the passkey backup state changed” from an ambiguous alert into a reproducible relying-party decision.

Explore the Refonte Learning API Developer Program. Review its published scope.