Introduction To WebAuthn API and Passkey
Introduction To WebAuthn API and Passkey
Save
Table of contents
What is FIDO?
FIDO2 or WebAuthn?
Scenarios
References
1.8K 20
License
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 1/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
Phishing!
Was killed by WebAuthn!… Or FIDO2… Hm… What do these terms even mean?
Well, if you are one of those confused readers, then welcome to my humble article. Sit
down. Get a cuppa tea, and let’s dig into the world of phishing proof passwordless
authentication.
What is FIDO?
FIDO, or FIDO Alliance is a consortium that develops secure, open, standard, phishing
proof authentication protocols. The FIDO Alliance was created in 2013, and now it has
over three hundred members across the globe. FIDO has three protocols: UAF, U2F,
and FIDO2. They are the same family of the protocols, since they are all origin based,
challenge-response, phishing proof, digital signature authentication protocols.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 2/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
The relying party(the server) sends a challenge and credential identifier of the
previously registered credential to the client(the browser). The client then attaches
relying party information, such as origin of the call, and sends it to the authenticator.
Authenticator first either checks if user is present, by requesting user to press the
button, or doing full user verification using on-device pin, biometrics, etc.
When verification is done, the device then signs the payload, using the private key,
identified by the credential id, and returns the assertion to the client. The client then
attaches information that it has given to the authenticator, as part of the signature
payload, and forwards it to the relying party.
The relying party checks that information, and ensures that the RP information
contains expected origin, and challenge, after which it checks the signature. If any of
those steps are fail, we can detect that there was a phishing attack, thus preventing it.
If you want to know more about the depths of FIDO protocols, you should check out
my 2016 KiwiPyCon talk slides “U2F authentication or why 2FA today is
wubalubadubdub”
FIDO2 or WebAuthn?
So there is general confusion about the terms. FIDO, FIDO2, WebAuthn, CTAP1,
CTAP2… What does this all even mean?
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 3/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
FIDO2 — A protocol name for a new, modern, simple, secure, phishing proof,
passwordless authentication protocol. It contains core specifications
WebAuthn(the client API) and CTAP(the authenticator API). There are other
“support” specifications which we will ignore in this article.
CTAP2 — A name for the second version of the CTAP protocol. The main
characteristic are use of CBOR for encoding structures, backwards compatibility
with U2F(CTAP1), extensions and new attestation formats. Both CTAP1 and
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 4/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
CTAP2 share the same transport layer, so the version difference is mainly
Open in app Get started
structural.
Platform — Basically operating system and it’s underlying FIDO client APIs, be it
system APIs or Browser. Basically Android, iOS, Windows, MacOS, Linux, etc.
Authenticator — A thing that authenticates user using FIDO protocol. FIDO2 has
two types of the authenticators: security keys, and platform authenticators.
Security Key — A physical device that connects via USB, NFC, or BLE. Example:
Yubikey, Trustkey, Feitian Biopass, etc.
WebAuthn API— A browser JS API that describes an interface for creating and
managing public key credentials.
TL;DR: WebAuthn — is the JS API. FIDO2 is the name for the whole protocol. The
right way to say about you authentication, is “Authentication with FIDO2" not
“Authentication with WebAuthn”, but that’s just semantics.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 5/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
Note: Make sure that you have enabled “Offer to save passwords” in Chrome
Upon the call you will see prompt to confirm your decision to store new
credential(username + password):
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 6/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
If there is only one credential, it will be returned by default, notifying the user about it:
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 7/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
When there is more than one credential available, the user will be prompted to select
one of the available ones.
So the basic methods are “store” and “get”. There is also “create”, but we will talk
about it in the next section.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 8/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
If you would like to learn more about Credential Management API I highly recommend
reading Eiji Kitamura’s article “Sign-in on the Web — Credential Management API and
Best Practices”
There are two operations you need to know about: MakeCredential and GetAssertion
Make Credential
Since credentials cannot be stored, as they are created on the authenticator, we call
“navigator.credentials.create”, to create new credential… (so much tautology)
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 9/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
user — Information about user. id, name and displayName fields are mandatory.
user.id — Server generated user identified. Must NOT contain any user
information. Should be randomly generated. It is used by the relying party as
user.name — Username. Can contain email, username, phone number, what ever
RP deems to be primary user identifier.
user.displayName — Actual user’s full name, like “John Bollocks” for example.
This is the basis for creating a credential. There are other optional keys such as:
authenticatorSelection.requireResidentKey /
authenticatorSelection.residentKey — Options of enforcing creation of
discoverable credentials. See “Discoverable Credentials” scenario.
When you call WebAuthn API you will see browser pops up with a choice of the
authenticator(at least on Chrome):
If you have a security key, then it will show it as one of the options, or otherwise it will
use browser/platform built-in authenticator. After you select your option, tap your
authenticator, or verify yourself using your fingerprint, after which you should see
“Success” pops up.
When you open your console, PublicKeyCredential object is returned by the WebAuthn
API.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 12/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
id/rawId — The credential identifier. This is what relying party is using to identify the
credential on the device by supplying it in the allowList, and exclude the authenticator
from accidental re-registration using the disallowList. rawId is a byte array. Where id is
a base64url encoded rawId.
type — A standard WebAuthn API type specified to signify to the RP that “public-key”
credential is used. Currently it is always “public-key” type, but in future there might be
other credential types.
type/id/rawId — Are all the same for both credential creation, and getting assertion.
response — Authenticator result. Different structures for credential creation and, and
getting assertion.
Relying party checking that challenge is set to an expected value, and thus preventing
MITM k Th i i fi ld h ll b h
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 d i i d i h 13/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
MITM attack. The origin field shall be set to the expected origin, and a miss-match
Open in app Get started
This structure may change in future, which is why the relying party must properly
decode the structure and validate the fields, and not use any form of template-based
validation.
AttestationObject
The result attestation is a CBOR map containing three fields: fmt — attestation format,
authData — freshly generated credential, and attStmt — the device attestation
It this example the attestation format is “none”, because we did not request attestation.
In this situation the platform will set attStmt to empty map, fmt to none, and device
aaguid in the authData will be 00000000–0000–0000–0000–000000000000. This is
done to preserve user privacy as attestation has inherit privacy issues. See
Demystifying attestation and MDS
leaving it undefined.
Open in app Get started
If you wish to learn more in depth information on attestation, you can read my article:
Demystifying attestation and MDS
If you explicitly need attestation, you can get it by setting attestation field in the call to
direct. This will prompt user consent (Popup).
Try it here
https://webauthnworks.github.io/FIDO2WebAuthnSeries/WebAuthnIntro/makeCredExample.attestationDir
ect
Get Assertion
After user adds the authenticator to his profile, they will be able to authenticate to
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 15/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
The allowList is not mandatory for discoverable credentials, but we will talk about
them little later.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 16/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
GetAssertion result contains some fields that are different from MakeCredential:
userHandle — user.id that is set when creating the credential. For U2F credential it
will be empty as U2F does not support user handle. This is useful for relying parties
that wish tie credential to their own index registry.
This structure is then returned to the server to be verified. How this done in details can
be found in my article: “WebAuthn/FIDO2: Verifying responses”.
Scenarios
In this section we will discuss various authentication scenarios that can be
accomplished with WebAuthn.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 18/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
As you can see here, this is a bit more abstract than previous examples, showing more
Open in app Get started
real life example.
First we perform user registration. Upon success we call “getMakeCredentialChallenge”
to obtain make credential challenge.
The fields are base64url encoded, because we cannot send buffers using JSON, so we
have to decode base64url encoded fields, by pre-processing request using
preformatMakeCredReq.
We then can call WebAuthn API with the formatted request, and the result attestation
is then encoded to JSON using publicKeyCredToJSON and sent to server, where server
verifies it.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 19/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
ㅤ
Open in app Get started
The login mostly the same as registration. User logs in with the previously registered
username and password.
The client obtains a login challenge. The challenge is received, it is decoded using
preformatGetAssertReq and passed to WebAuthn API.
The response then encoded and forwarded to the server. If server successfully verifies
it, it will return status: ok.
ㅤ
ㅤ
ㅤ
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 20/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
But in “passwordless authentication” these are different terms. RP only sees the
assertion that is generated by the authenticator, and the user verification is done by the
authenticator through the biometrics, pin or any other user verification methods.
User verification is crucial to this scenario. If the relying party does not enforce user
verification, it will have no idea if the user claim is authentic, therefor, the
authentication is no longer multifactor, as the only factor left is users device proof. This
means that for the attacker to get access to the account it would require only a
username and security key.
So to avoid these attack scenarios, when a user is going to create a credential, we will
add “userVerification” set to “required” to the makeCredential call.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 23/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
The first thing you notice in the workflow is lacking password field, hence the
passwordless authentication.
Next difference you can see is “userVerification” set to “required”. This will force the
authenticator to perform user verification using one of the available
methods(biometrics, clientPin, etc). If the authenticator does not support user
verification, the command will fail with an error.
When the relying party receives the response, it will decode authData, and check that
UV flag is set to “true”.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 24/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 25/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
Now, are you curious to see what would the process of passwordless authentication
look like?
Try it here:
https://webauthnworks.github.io/FIDO2WebAuthnSeries/WebAuthnIntro/PasswordlessExample.html
builtin authenticator that we call platform authenticator. That means that any website
Open in app Get started
can start using FIDO without requiring purchasing security keys.
Platform authenticators are system wide, which means that all browsers will have
access to the same keystore, and thus registering credential with Chrome would mean
that it is still accessible in Firefox.
Beware that as of right now, Jan 2021, MacOS is still in active development, and so
Chromium based browsers will have a separate credentials, and UI/UX experience,
from Safari. This will change is future.
Platform support
Platform authenticator are available for these platforms:
MacOS 10.15+
Android 8+
iOS 14+
Detection
To detect if platform supports FIDO authentication, you can use
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() :
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 27/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
This is a little more than you usually need. Most of the browsers support WebAuthn
API. But there are some outliers like “Samsung Internet” and many smaller browsers
that do not support it yet.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 28/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
When calling platform API, users will, by default, be asked if they want to register with
the platform authenticator or security key.
If you want user to only see platform option, you must set
authenticatorSelection.authenticatorAttachment to platform. (note: cross-platform is
for security keys only)
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 29/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
From relying party perspective, there is no change in the attestation response, but you
may wish to add some flag, note, in your database entry to signify that this is a
platform credential, for things like analytics and user experience.
During the GetAssertion, nothing really changes. The relying party may want to specify
that credential is platform by specifying in the credential descriptor, transports field
value “internal”:
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 30/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
And just like that you are able to use platform authenticators to enable FIDO for any
user.
To tie the result credential relying party has two important identifiers: id and
userHandle. The relying party can identify the credential using either a credential id,
or userHandle, which is what relying party sets user.id when it registers a credential.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 31/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
The relying part is then able to find the user, by searching the one that has an
authenticator with the corresponding id or userHandle.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 32/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 33/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
During the authentication, the relying party must only send a challenge. This is
because we are forcing platform to switch to discoverable credentials mode.
The relying party will find the user by either using id or userHandle values.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 34/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
And with username removed, we are down to One, Single, Login button:
https://webauthnworks.github.io/FIDO2WebAuthnSeries/WebAuthnIntro/UsernamelessExample.html
Like in Apple’s sweetest dream, we came up with the best authentication experience
people ever wanted. A press of button.
As of right now, relying parties can start to add this feature in their API calls when
creating discoverable credentials, but the support for the residentKey field may lack
for a while.
1. Privacy issues in CTAP2.0 — For CTAP2.0 the platform may call any RK credential
without any user verification. This means that theoretically, you may be using your
security key for some “naughty” website. Then an attacker, like airport security, can
just plug your security key in their fancy bruteforcer, which will check if there is a
credential for that naughty website. This is fixed in CTAP2.1. We will discuss it
shortly.
2. Lack of credential management in CTAP2.0 — For CTAP2.0, user may not manage
their credentials. Security keys have very limited storage, 25–50 credentials, and so
the storage can be filled rather quickly. The only way to remove credentials is to
reset, wipe, the entire device. This is again, fixed in CTAP2.1
These changes are still six to twelve months away (as of Jan 2022) from support in
platforms, and security key with the support of CTAP2.1 are just arriving on the
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 36/38
p
8/7/22, 11:53
, y y pp j g
Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
market, so it will be some time before we will everything coming into place.Get started
Open in app
References
https://w3c.github.io/webauthn
https://medium.com/@WebauthnWorks/verifying-fido2-responses-
4691288c8770
https://medium.com/dev-channel/sign-in-on-the-web-credential-management-
api-and-best-practices-d21aed14b6fe
https://slides.com/herrjemand/fido-u2f-kiwipycon-2016
https://webauthnworks.github.io/FIDO2WebAuthnSeries/
https://github.com/herrjemand/WebauthnAwesome
Updates
20/01/2019 — Updated passwordless section per advice from @Serianox_
License
This article is licensed under Creative Commons Attribution-NonCommercial-
NoDerivatives 4.0 International (CC BY-NC-ND 4.0). So you are free to read, share, etc.
If you are interested in commercial use of this article, or wish to translate it to a
different language, please contact ackermann(dot)yuriy(at)gmail(dot)com.
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 37/38
8/7/22, 11:53 Introduction to WebAuthn API and Passkey | by Ackermann Yuriy | WebAuthn Works | Medium
https://medium.com/webauthnworks/introduction-to-webauthn-api-5fd1fb46c285 38/38