It’s part of the “Web authentication API” (webauthn) and uses the PublicKeyCredential interface available in the browser. Those APIs can be used for various things and support a number of options, none of which are called “passkeys,” making it confusing if you are just getting started in trying to implement passkeys, residentKey is what you’ll actually see in code and the documentation will also refer to them as “discoverable keys.” How tou use those browser APIs also depends on how you want your authentication process to flow: do you want the device to potentially trigger the passkey UI before you know who they are (this is what is meant by discoverable), or do you want the user to first provide a username/email and then trigger the passkey UI once you know your system has their public key.
The gist is that passkeys are private/public key pairs generated on the user’s device (or in something like 1password) via the JavaScript API, the private key is used to sign a challenge (random bytes previously generated on the server) on the device and the public key is used to verify the signature on the server.
There are two flows: creating a passkey and authenticating with a passkey. In both flows the server first generates and stores the challenge, sends the challenge to the client, which is included in the webauthn API call. The result of the creation API includes public key which needs to be stored by the server for future authentication flows. The result of the authentication API includes a signature of the challenge which the server needs to verify using the previously stored public key.
I recently spiked adding passkeys to what’s generated by phx.gen.auth in Phoenix 1.8 RC: First pass as passkeys · jswanner/phx-passkey-spike@dd88cf9 · GitHub






















