Registration is where a user hands you a public key. Everything you will later rely on depends on doing these six steps properly.
The six steps
- Your server generates creation options: a random challenge, the relying party identity, the user handle, and your policy.
- The browser passes them to the authenticator.
- The authenticator creates a key pair, keeps the private half, and signs an attestation object.
- The browser returns that object to your server.
- Your server verifies it: the challenge, the origin, the relying party hash, the flags, the signature.
- You store the credential identifier, the public key, and the sign counter.
The challenge must be yours, once
Generate it server side, at least sixteen random bytes, store it against the session, and delete it after one use. A challenge that can be replayed is not a challenge.
The mistake to avoid: generating it in JavaScript. The whole ceremony rests on the server having chosen a value the client could not predict.
The user handle is not the username
The user handle identifies the account to the authenticator. It ends up stored on the device, sometimes shown in a system dialogue, and it is not the place for an email address or anything else you would rather not see there.
Use an opaque, stable identifier, sixty-four bytes at most. A random value mapped to your account in your own database is the right answer.
The origin check is the anti-phishing property
The browser records the origin it was on and the authenticator signs over it. Your server checks it matches. That single check is what makes Webauthn phishing-resistant, and it is why a lookalike domain cannot obtain a usable response.
Related: version 5.3.4 of the framework fixed a case where cross-origin responses were accepted when no top-origin validator was configured. The safe default is to refuse, and it now does.
In Symfony
composer require web-auth/webauthn-framework
The bundle exposes the routes and the ceremony, and a Stimulus component handles the browser side. The documentation covers the configuration; the next article covers what happens when the user comes back.