Detecting Platform Authenticator Availability

The platform-authenticator probe answers one narrow question: does this device have a built-in authenticator that could answer a ceremony. It is the right input for deciding whether to offer enrolment and the wrong input for almost everything else. This page covers what it reports, where it belongs in the flow, and the mistakes that turn a helpful capability check into a lockout. It sits under Progressive Enhancement and Passkey Fallback Flows.


Probe Reference

Probe Answers Latency Can reject
API presence is the credential API available at all synchronous no
platform authenticator available is there a built-in authenticator asynchronous, milliseconds yes, on some engines
conditional mediation available can passkeys appear in autofill asynchronous, milliseconds yes

All three are independent. A device can have the API and no built-in authenticator; it can have a built-in authenticator and no autofill support; it can have both and hold no credentials at all.

What the probe does and does not answer It reports a device capability, not a user state, and the distinction drives every decision built on it. Capability, not readiness, and never credential existence a built-in authenticator exists the device has one and it is usable in principle enrolment may be worth offering the ceremony has something that could answer it the user will succeed not answered — they can still decline the user already has a passkey never answered — that is a server-side question

Root Cause Analysis

1. Using it to gate sign-in. The most damaging misuse. A user whose passkey lives on their phone, signing in on a desktop with no built-in authenticator, gets a negative probe — and if that hides the passkey button, the cross-device flow they needed is now unreachable.

2. Treating it as a readiness check. A positive result means a device exists, not that it is enrolled, unlocked, or that the user will consent. Enrolment can still fail for entirely ordinary reasons, and the interface must handle that.

3. Blocking the render on it. It resolves in milliseconds, but “milliseconds” is not “always”, and a promise that never settles on some engine will leave the sign-in page in a loading state forever if the layout waits for it.

4. Not handling a rejection. Some engines throw rather than resolving false, particularly in hardened or embedded contexts. An unhandled rejection in the probe takes out the rest of your initialisation.

5. Caching the answer across sessions. Users plug in security keys, update operating systems and enrol biometrics they did not have last week. A persisted negative hides the passkey path indefinitely.

Where the answer belongs in the flow Probe on mount, use it only to decide whether to offer enrolment, and let the ceremony decide the rest. One probe, one decision, no blocking page load probe resolves in milliseconds layout offer enrolment or do not user acts ceremony runs outcome success or an ordinary refusal Nothing on the critical sign-in path waits for this — a probe that never resolves must leave a working page behind it.

Step-by-Step Resolution

Step 1 — check API presence first, synchronously

If the credential API is absent there is nothing to probe, and the page should render its password form and stop.

Step 2 — wrap the probe so it cannot reject

Catch and coerce to false. The conservative answer is always safe, because the fallback is a working page.

Step 3 — probe once per page load, in memory

Module scope, not component state, and never persisted to storage.

Step 4 — use the answer only for the enrolment offer

Positive means offer enrolment on this device. Negative means offer a security key, or the cross-device path, or simply do not offer enrolment here.

Step 5 — leave sign-in alone

The passkey sign-in button stays visible regardless, because the credential may live somewhere else entirely.

Step 6 — reserve layout space

Render the container at its final height from the server so a resolved probe fills it rather than inserting an element under the user’s cursor.

Enrolment versus sign-in The probe belongs on the enrolment decision and has no business gating sign-in. It answers an enrolment question only use it for deciding whether to offer enrolment choosing which enrolment copy to show deciding whether to suggest a security key instead do not use it for hiding the sign-in passkey button deciding whether the user has a credential gating the password form anything security-relevant Hiding the sign-in button on a negative probe strands users whose passkey lives on a phone and is reachable by the cross-device flow.

Verification and Testing

Stub the probe to false and assert the page still renders a complete sign-in surface, that no enrolment offer appears, and that the passkey sign-in button is still present. That last assertion is the one that catches the gating mistake.

Stub it to reject and assert the same. Real engines do this, and an unhandled rejection is indistinguishable from a broken page.

With a virtual authenticator configured as an internal transport, assert the probe returns true and the enrolment offer appears. Remove the authenticator and assert the offer disappears on the next load but the sign-in path does not.


Pitfalls

1. Hiding the passkey sign-in button on a negative probe. Strands cross-device users.

2. Persisting the result. Guarantees a stale answer for anyone whose device gained support.

3. Awaiting it before first paint. Turns a capability check into a rendering dependency.


Frequently Asked Questions

Does a positive result mean the user has a passkey?

No, and nothing in the browser will tell you that. Credential existence is deliberately unobservable to a page; it is a question you answer from your own records once the user has identified themselves. The probe reports hardware capability only.

Should I offer enrolment when the probe is false?

Offer a different enrolment path rather than none. A device with no built-in authenticator can still enrol a security key, and a user who wants a passkey on their phone can be pointed there. What you should not do is present the same “set up a passkey on this device” copy that a positive probe would have earned.

Why do some browsers reject instead of returning false?

Because the check touches platform surfaces that may be unavailable in hardened, embedded or policy-restricted contexts, and the resulting failure surfaces as a rejection rather than a negative answer. Coercing both to false at the boundary makes the difference irrelevant to the rest of your code.

Is there a probe for whether a security key is connected?

No, and there should not be — enumerating attached authenticators would be a fingerprinting surface. The way to find out is to run the ceremony and let the user choose, which is why the sign-in button stays visible whatever the platform probe says.

How does this interact with the conditional-mediation probe?

They are independent and both worth running. A device can support autofill without having a built-in authenticator, because the credential may arrive over the cross-device flow. Treating one as a proxy for the other produces a page that hides the wrong thing.

Should the result be sent to analytics?

Aggregate counts are useful for understanding your population and deciding when to promote the passkey path. What to avoid is attaching the result to a user record alongside other device attributes, which turns a capability check into a fingerprint you did not previously hold.



Choosing the Enrolment Copy from the Result

The probe’s real value is that it lets you write two different enrolment offers instead of one vague one, and the difference in conversion between a specific offer and a generic one is large.

When the probe is positive, name the device. “Set up a passkey on this Mac” or “Use Touch ID to sign in next time” tells the user exactly what is about to happen and what they will do next time. The platform prompt that follows will match the expectation you just set, which is what stops the biometric dialog reading as an interruption.

When the probe is negative, offer the alternatives explicitly rather than falling silent. A security key is enrollable on almost any device, and a user who wants their passkey on a phone can be told to set it up there. “This computer does not support passkeys” is both slightly untrue and unhelpful; “Set up a passkey on your phone, or use a security key” gives them something to do.

When the API is absent entirely, say nothing about passkeys at all. There is no action available, and an offer the user cannot act on is noise that trains them to ignore the next one.

It is also worth deciding what happens on a device where the probe is positive but the user has already enrolled a credential on it. You know this from your own records rather than from the probe, and the right offer at that point is not another enrolment but a reminder that they can sign in with what they already have — which is the case a settings page usually handles better than a prompt.

Related