Employing FIDO authenticators and the WebAuthn API in your sign-in flows: A guide for relying parties
Account Bootstrapping: “Bootstrapping an account on a device”, or “bootstrap sign-in”.
Starting from scratch[1], a relying party authenticates a user. For example, this happens when a user puts their existing account on a newly-purchased phone. Or when a user logs into a website for the first time in a given browser instance. Or when a user logs into a website in a private browsing session (which doesn’t have cookies and other state from the main browsing session). Or when a user signs into a mobile app for the first time on a given device. Note that this isdifferent from creating an account with a service in the first place.
Reauthentication happens when a relying party already knows who the user is, but would like to reconfirm this. For example, this happens before making sensitive changes to an account (add a recovery email address, change the passwords, etc.): a relying party would typically ask the user to re-enter their password or perform some other action to reconfirm their control of the session. Likewise, when a mobile app asks the user to sign in every time the app starts (or a web site asks the user to sign in again after a period of inactivity), this is technically areauthentication, since the app or web site can choose to remember the user’s authentication state after the account has been bootstrapped on the device, e.g., by setting cookies.
Relying Party (RP): The website that is trying to ascertain the identity of the user or perform FIDO authentication.
Signing in: This can refer to either account bootstrapping or reauthentication. When in doubt, we will use the latter, more descriptive, terms in the sections below.
Logging in: seeSigning in.
Login challenge: A prompt served to the user that they need topass. For example, a prompt asking the user for their password is a login challenge. A prompt asking the user to confirm sign-in on another device (e.g., their phone) is a login challenge. A prompt asking the user to insert and activate theirsecurity key is a login challenge. Account bootstrapping and reauthentication usually consist of serving the user one or more login challenges.
Authentication factor: Information provided by a user (or one of the user’s devices) for purposes of authentication, usually in response to a login challenge. Often categorized into “knowledge factors” (e.g. passwords), “something you have” factors (e.g. another already signed-in device), and “something you are” factors (e.g. biometrics). Note that a single login challenge may collect multiple factors simultaneously.
2FA: 2-factor authentication (akaMFA: multi-factor authentication). This refers to a contract between a user and a relying party where the relying partymust collect at least two distinct authentication factors from the user during a bootstrap sign-in.
2FA user: a user whose account has 2FA turned on, i.e., who must present 2 authentication factors during sign-in.
Roaming authenticator: a FIDO authenticator usable with any device the user is trying to sign-in from. Roaming authenticatorsattach to users’ devices in varying fashions. For example: via USB, NFC, or Bluetooth. These authenticators are often referred to as “Security Keys”. A smartphone can also act as a roaming authenticator.
Platform authenticator: a FIDO authenticator that isbuilt-into a user’s device.
UVRA:User-verifying roaming authenticator. UVRAs canverify[2] individual users through the use of biometrics, or through the user typing a PIN or password, etc. An important class of UVRAs aresmartphones, in which case the “attachment” typically happens over a wireless connection.
It’s important to understand that different types of authenticatorsunlock different use cases and user experiences. The webauthn/FIDO APIssupport these different use cases, but relying parties must take care toutilize the APIs correctly, e.g., by requesting the appropriatetransport or attachment type for the particular use case they areaddressing. If not done correctly, you risk confusing your users, makingauthentication more complicated than necessary for them, or locking themout of their account. Below is an overview of the use cases unlocked bythe different types of authenticators:
Physical manifestation of the authenticator | ||||
---|---|---|---|---|
Platform | Roaming | |||
Capabilities of authenticator | User-verifying |
|
| |
Not-user-verifying |
|
|
Below we will get into more detail of how relying parties shouldimplement support for these different use cases, but we will approachthis from a user-journey perspective: what should you (as the relyingparty) do during the login step, during the reauthentication step, etc.
This section applies when the relying party doesn’t know yet who iscontrolling the client device. There is no cookie, no credential id,etc., available to the relying party, although for now we assume thatthe user already has an existing account with the relying party.
To bootstrap an account on a device, serve the user a sign-in page.Typically you would start off by asking the user for their accountidentifier (username)[6]:
Once it’s clear who the user claims to be, appropriately serve furtherlogin challenges to the user. This may or may not include asking theuser for their password, and may or may not include serving FIDOchallenges for 2FA users (see below for how to use FIDO for 2FA). Thismay even include “account recovery” steps in case the user has forgottentheir password or is otherwise not able to pass the regular loginchallenges. Once the user has passed all the login challenges, they’reconsideredauthenticated andsigned in.
What happens when the user doesn’t already have an account with therelying party? Usually, you will give users the option on the sign-inpage to create an account[7]. If the user chooses that option, collectthe necessary information from the user to open a new account. If theuser successfully opens a new account, they’re also consideredauthenticated and sign-in.
Once the user is signed in (either because they bootstrapped theiraccount on the device by passing one or more login challenges, orbecause they just created a new account at the relying party), make acall to:
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
If that call returns true, then the user’s system features a FIDOplatform authenticator, and you can offer the user the convenience ofusing FIDO-based reauthentication in the future:
Serve an opt-in page to the user offering biometric reauthentication:
Consider showing (or linking to) longer descriptions explaining that allusers that are able to unlock the current device will be able to accessthe account at the relying party to ensure that the user is giving fullyinformed consent.
If the user consents, callnavigator.credentials.create()
, making sureto ask for a platform authenticator and user verification:
navigator.credentials.create({publicKey:{rp:{...},user:{...},challenge:...,pubKeyCredParams:{type:"public-key",alg:-7},authenticatorSelection:{authenticatorAttachment:"platform",// !!!userVerification:"required"// !!!},}})
A note on attestation: We recommend that most relying parties operating in theconsumer (as opposed to enterprise) space not specify the attestation conveyance parameter
attestation
(thus defaulting to none), or instead explicitly use the valueindirect
. This guarantees the most streamlined user experience (platforms are likely to obtain consent from the user for other types of attestation conveyances, which likely results in a larger fraction of unsuccessful credential creations due to users canceling the creation).
Associate the returned public key and credential id with the useraccount. Also, make sure you associate the credential idwith thedevice the user just authenticated from. For example, store thecredential id in a cookie (or associate it with a cookie), or store thecredential id in local storage.
Reauthentication might happen for the following reasons:
The user signed out and now wants to sign in again.
The user session expired due to inactivity, and the user wants tosign in again.
The user is about to perform a sensitive action, and needs tore-confirm control over the user session.
Let’s look at the last case first: when it’s time to re-authenticate fora sensitive action, check whether you have a credential id for this userfor the purpose of reauthentication, i.e., the kind of credential idobtained fromopting the user into FIDO-basedreauthentication. Makesure it’s associated with the userand device - for example, check acookie or read from local storage.
Ifno credential id is available, serve a traditional login challengesuitable for reauthentication[8], for example:
If, however, youdo discover a credential id for the current session,then you can use FIDO-based reauthentication:
When the user is ready (in the above example, when they click on the“Go!” button), callnavigator.credentials.get()
, again requiring userverification and specifying an “internal” transport:
navigator.credentials.get({publicKey:{challenge:...,rpId:...,allowCredentials:[{type:“public-key”,id:...,//!!! use the *one* credential id associated with//!!! this user/device combination.transports:[“internal”]//!!!}],userVerification:“required”,//!!!}})
If the user instead clicks on “Try another way”, you should offer themother login challenges (password, etc.) to reauthenticate them.
Now let’s look at the case where the reauthentication is triggeredbecause the user logged themselves out, or the relying party expired theuser session. To facilitate this, the relying party would have to keepsome form of secure user session state (unforgeable cookie, etc.) evenwhen they consider the user signed-out,[9] allowing it to give theuser a more convenient user experience. You, as the relying party, mightserve a sign-in page like this:
(An alternative UI treatment here could be anaccount chooser-styleUI, especiallywhen the relying party allows multiple accounts to be signed-in at thesame time.)
If the user clicks on “Use a different account”, then you should enteran account bootstrap flow as explained above, repeating the steps inAuthenticating theUser andOpting into FIDO-basedReauthentication,presumably with a different account. In this case, you should also givethe user the ability to completely remove their account from beinglisted on the sign-in page.
If the user clicks on “Next”, then check whether you have a credentialid associated with the user and device (for example, check a cookie orread from local storage). If no credential id is available, serve atraditional login challenge suitable for reauthentication, for example:
If, however, youdo find a credential id for the current session, thenyou can use FIDO-based reauthentication:
When the user is ready (in the above example, when they click on the“Go!” button), call navigator.credentials.get(), again requiring userverification and specifying an “internal” transport:
navigator.credentials.get({publicKey:{challenge:...,rpId:...,allowCredentials:[{type:“public-key”,id:...,//!!! use the *one* credential id associated with//!!! this user/device combination.transports:[“internal”]//!!!}],userVerification:“required”,//!!!}})
If the user instead clicks on “Try another way”, you should offer themother login challenges (password, etc.) to reauthenticate them.
The login flows shown above don’t fundamentally change the securityposture of your user accounts. If, for example, your account bootstrapflow consists of asking the user for only a username and password, thenopting them into FIDO-based reauthentication (as shown above), stillleaves the user vulnerable to phishing attacks. Using user-verifyingplatform authenticators for reauthentication is simply a way to makereauthentication easier to use, it’s not a way to make the accountresistant to phishing attacks.
To actually reduce the exposure of your users to certain phishing risks,you can offer them the ability to use FIDO-based roaming authenticatorsas 2nd factors when bootstrapping their account.[10]
Note: Wedo not recommend allowing users to register user-verifying platform authenticators as second factors for account bootstrapping. If you want to give your users the convenience of biometric sign-in, followthesteps above to register a user-verifying platform authenticator as a passwordreplacement forreauthentication,not as a second factorfor account bootstrapping.
This is ok to do even for your 2FA users, who might expect two different login challenges for a sign-in-after-sign-out reauthentication: the platform authenticator represents somethingthe userhas, and it will verify something the userknows (PIN) oris (biometric).
Have your users register their roaming authenticators on a page thatthey normally use for security purposes such as 2FA sign-up, passwordchanges, etc. In particular, we donotrecommend in-lining thisopt-in choice as part of the user’s sign-in flow,unless your sitemakes 2FA mandatory[11].
Typically, you would have a page like this:
When the user clicks on “Add a security key”, you callnavigator.credentials.create()
, taking care to specify “cross-platform”for the attachment type. You should also look up any existing credentialids for 2FA authenticators already registered for the current user (youcan ignore credential ids for platform authenticators), and specifythose in the exclude-list, thus ensuring that a user doesn’t registerthe same authenticator twice:
navigator.credentials.create({publicKey:{rp:{...},user:{...},challenge:...,pubKeyCredParams:{type:"public-key",alg:-7},excludeCredentials:[{//!!! Credentials already on file fortype:"public-key",// this user. These are just examples.id:newUInt8Array([21,31,56,...]).buffer,transports:["usb","nfc"]},{type:"public-key",id:newUInt8Array([21,31,56,...]).buffer,transports:["internal","ble"]},{...}],authenticatorSelection:{authenticatorAttachment:"cross-platform",//!!!// for the 2FA case, leave userVerification unspecified},}})
A note on attestation: We recommend that most relying parties not specify the attestation conveyance parameter attestation (thus defaulting to none), or instead explicitly use the value indirect. This guarantees the most streamlined user experience (platforms are likely to obtain consent from the user for other types of attestation conveyances, which likely results in a larger fraction of unsuccessful credential creations due to users canceling the creation).
It is common practice to let the user name the authenticator (eitherbefore or after you callcreate()
), and to show the user a list ofregistered authenticators on this page, or a related accounts settingspage, where they can deregister individual authenticators.
Once they register a roaming authenticator, users can now secure theirbootstrap sign-ins by using this authenticator as a 2nd-factor duringsign-in.[12]
The relying party starts the bootstrap sign-in flow as usual, typicallyby asking the user for their account identifier (username)[13]:
Once it’s clear who the user is, serve appropriate login challenges tothe user. Typically this will include asking the user for a password,but it might not. At some point (perhaps directly after collecting thepassword), you serve a login challenge for the FIDO 2nd-factor:
When the user clicks on “Next”, callnavigator.credentials.get()
,specifying all the credential ids you have on file for this user’sroaming 2FA authenticators:
navigator.credentials.get({publicKey:{challenge:...,rpId:...,allowCredentials:[{//!!! make sure you specify thesetype:"public-key",id:newUInt8Array([21,31,56,...]).buffer,transports:["usb","nfc"]},{type:"public-key",id:newUInt8Array([21,31,56,...]).buffer,transports:["internal","ble"]},{...}],//!!! no need to specify userVerification parameter}})
Note that the browser or platform OS will prompt the user at this pointto use their security key. Here is an example of what this might looklike in Chrome on Linux:
Upon touching their authenticator, you will receive aPublicKeyCredential object containing aAuthenticatorAssertionResponsewhich you need to successfullyverifybefore considering the user authenticated and signed-in.
Note that in what we’ve discussed so far, the user would have to useanother authentication method - such as a password - to bootstrap theaccount on a device before they can opt into FIDO-basedreauthentication; and they also would typically use anotherauthentication method - such as a password - in conjunction with aroaming FIDO authenticator to implement phishing-resistant 2FA.
User-verifying roaming authenticators (UVRA) unlock trulyFIDO-only/passwordless use cases, such assingle-step accountbootstrapping. A UVRA inherently meets the 2FA security bar, since itrepresents something the userhas (the authenticator), and it willalso verify something the userknows oris (PIN or biometric). Infact, like any type of FIDO authentication, UVRAs provide phishingresistance, thus exceeding the security level of many other forms of2FA. Login flows built around UVRAs are therefore suitable not just forthe general population, but even for high-security users such as 2FAusers.
Yet, the user experience is that of a single-step sign-in: the usersimply uses the authenticator to bootstrap their account on anotherdevice, without needing to also provide a password or passing otherlogin challenges on that device[14].
Note that one important class of UVRAs are mobile phones, which we’llhandle in more detail below. This section deals with other forms ofUVRAs (such as special-purpose hardware tokens with PIN protection or afingerprint scanner), or with relying parties that don’t wish to takeadvantage of the more streamlined user experience that are possible whenusing a phone as a UVRA.
Users need to set up their UVRA so it can be used in aFIDO-only/passwordless login flow. We recommend that relying parties dothisoutside of the normal login flow, unless the relying partyknows that the user is in possession of a UVRA device (in which caseregistering the UVRA can be done as part of the login flow). For mostconsumer use cases, the relying party won’t know whether the userpossesses a UVRA, and therefore should promote the use of UVRAs to usersoutside of the login flow. For the purpose of this guide, we assume thatthe relying party has somehow advertised its support of UVRAs, and issuggesting that users possessing a UVRA device go to a registration pagethat might look like this:
When the user clicks on “Register your security key”, you callnavigator.credentials.create()
, taking care to specify “cross-platform”for the attachment type, requiring user verification, and requiring aresident (aka discoverable) key[15]. You also want to look up anyexisting credential ids for UVRAs already registered for the currentuser (you can ignore credential ids for platform authenticators and 2FAauthenticators), and specify those in the exclude-list, thus making surethat a user doesn’t register the same authenticator twice:
navigator.credentials.create({publicKey:{rp:{...},user:{...},challenge:...,pubKeyCredParams:{type:"public-key",alg:-7},excludeCredentials:[{//!!! UVRAs already on file fortype:"public-key",// this user. These are examples.id:newUInt8Array([21,31,56,...]).buffer,transports:["usb","nfc"]},{type:"public-key",id:newUInt8Array([21,31,56,...]).buffer,transports:["internal","ble"]},{...}],authenticatorSelection:{authenticatorAttachment:"cross-platform",//!!!requireResidentKey:true,//!!!userVerification:"required"//!!!},}})
A note on attestation: We recommend that most relying parties not specify the attestation conveyance parameter
attestation
(thus defaulting to none), or instead explicitly use the valueindirect
. This guarantees the most streamlined user experience (platforms are likely to obtain consent from the user for other types of attestation conveyances, which likely results in a larger fraction of unsuccessful credential creations due to users canceling the creation).
You should let the user name the authenticator (either before or afteryou call create()), and show the user a list of UVRAs that they haveregistered on this or a related accounts settings page.
Technically speaking, phones can be registered the same way as otherUVRAs. The browser or platform that is providing the webauthn API willtypically provide a way for the phone and browser to directly connectwirelessly, so that a FIDO credential can be generated as justdescribed.
There is, however, a better way: relying parties have the opportunity toregister the phone as a UVRA if and when the user is interacting with amobile app belonging to the relying party, or by visiting the relyingparty’s website on the phone. We call thison-device registration.
On-device registration for using the phone as a UVRA is very similar toopting the user into FIDO-based reauthentication on the phone. In fact,we recommend that the relying party re-use the same moment - duringaccount bootstrapping of the account on the phone and afterchecking that a user-verifying platform authenticator exists - to optthe user both into FIDO-based reauthentication on the phone,andinto using the phone as a UVRA:
We recall the recommended steps during an account bootstrap. First,after the user is authenticated, make a call to
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
If that call returns true, you can prompt the user to opt intoFIDO-based reauthentication. If the user is on a platform that can beused as a UVRA, you can also tell them about passwordless functionality:
Consider showing (or linking to) longer descriptions explaining that allusers that are able to unlock the current device will be able to accessthe account (and to bootstrap it on new devices), in order to ensurethat the user is giving informed consent.
Note: One issue here is that you won’t know whether the underlying platform supportsUVRA functionality (i.e., if it’s really a mobile phone) until you receive the registration response and inspect the indicated transports, especially since browsers are moving to a model where user-agent strings are becoming less and less revealing about the user’s device type. We therefore recommend using language like shown above implying that this UVRA functionality may or may not work.
If the user consents, call navigator.credentials.create(), making sureto ask for a platform authenticator, user verification, and a resident(discoverable) key:
navigator.credentials.create({publicKey:{rp:{...},user:{...},challenge:...,pubKeyCredParams:{type:"public-key",alg:-7},authenticatorSelection:{authenticatorAttachment:"platform",//!!!requireResidentKey:true,//!!!userVerification:"required"//!!!},}})
A note on attestation: We recommend that most relying parties not specify the attestation conveyance parameter
attestation
(thus defaulting to none), or instead explicitly use the valueindirect
. This guarantees the most streamlined user experience (platforms are likely to obtain consent from the user for other types of attestation conveyances, which likely results in a larger fraction of unsuccessful credential creations due to users canceling the creation).
If the transports indicated in the response include “ble” and/or“cable”, you know that the present device can be used as a UVRA.Register the returned credential id both as a credential id forreauthentication as well as a UVRA for this user. You might want to tellthe user about this:
If the transports indicated in the response only include “internal”, butnot “ble” and/or “cable”, the user can still use this platformauthenticator for FIDO-based reauthentication on this phone, but willhave to use other mechanisms to bootstrap their account on otherdevices. You might want to inform the user about this:
If the response indicates that the device cannot be used as a UVRA,register the returned credential id just as a credential id forreauthentication.
If the user registers their phone as a UVRA this way, consider creatinga page in your account settings that shows the user a list of theirregistered UVRAs, and allow for deregistering them. There is no need tolet the user name their UVRA if it’s a phone - you can instead refer toit by its model name.
If you have users amongst your user population that have UVRAs (eitherUVRA Security Keys, or UVRA-phones), then you can offer aFIDO-only/passwordless bootstrap sign-in flow. This boils down tocallingnavigator.credentials.get()
with an empty allow-list duringaccount bootstrap. At some point, when most of your users use UVRAs, youmight consider making this the default login flow (with legacy methodssuch as passwords being used as fallbacks). But for the time being, weimagine that the FIDO-only login flow will be an advanced option in youraccount bootstrap flow, which might be promoted like this:
If the user clicks on “Sign in without a password!”, with or withouthaving supplied a username, callnavigator.credentials.get()
without anallow-list, making sure you require user verification:
navigator.credentials.get({publicKey:{challenge:...,rpId:...,userVerification:"required",//!!!}})
The result will include a credential id and user handle, which you canuse to figure out which user just authenticated. If the call fails, makesure you give the user other options to sign into their account, such aspassword-based flows or flows involving other types of login challenges.
A concern around the use of FIDO authenticators is device loss: whathappens when a user loses their FIDO authenticator? How will they beable to get back into (i.e., “recover”) their account?Our generalrecommendation is to encourage the user to register asecondauthenticator as backup, but there are a few caveats to consider:
If a user’sonly registered authenticator is aplatformauthenticator that is usedonly forFIDO-basedreauthentication,then the user presumably has some other means to performbootstrapsign-ins. Thus, the user doesnotnecessarily need to register a second authenticator, becausethe user will not be “locked out” of their account if they loseaccess to their platform authenticator. By definition, this“re-authentication-only” authenticator is used to simply bypass adifferent, more onerous login challenge (such as a password)during reauthentication - itmustnot be used for accountbootstrap. Thus, the user will have other means to perform accountbootstrap, and if needed, register a new platform authenticatorfor FIDO-based reauthentication.
If the user has roaming authenticators registered that are usedduring account bootstrap (e.g., as a 2nd factor, or as a UVRA forasingle-step account bootstrap), there might still be otherways for the user to bootstrap their account on a new device. Forexample, the user might be a 2FA user that has both a security keyand a HOTP-based 2nd-factor token registered for their account. Ifthis is the case, the loss of the security key still doesn’t meanthat the user will have lost access to their account. (Althoughthis also means that the account isn’t getting fullphishing-resistant protection.)
This leaves us with a scenario in which the user is a“FIDO-only”user, meaning that theymust use a roaming FIDO authenticatorduring account bootstrap (either a UVRA, or a simpler authenticatorsuitable as a second factor). In this case the relying party shouldencourage the user to register asecondroaming (cross-platform)authenticator.Do not let the user register a platform authenticatoras a backup for a roaming authenticator (and, as we mentioned above,don’t bother registering backups for platform authenticators that areonly used for re-authentication).
Allow the registration of the second (backup) authenticator to happenover any authenticated user session: as we noted above, those sessionsby definition were bootstrapped by another FIDO authenticator, so thesecurity of the session is sufficient for this registration step.
So far we considered two different ways a relying party can achievephishing resistance for a user: either ask the user to register a simple(not necessarily user-verifying) roaming authenticator that is then usedas a 2nd factor during account bootstrap, or ask the user to register aUVRA, which provides two authentication factors and phishing resistancein single-step account bootstrap flows.
What if the relying party is primarily interested in providing phishingresistant account bootstrap flows to its users, but it wants to beflexible as to whether this happens through a 2nd step (e.g., using anon-user-verifying security key), or whether this happens through theuse of a UVRA and single-step account bootstrap? Webauthnimplementations compatible with Level 2 of the webauthn specificationcan support such a scenario. As a result, the relying party cancustomize the user experience to the individual user: if a user is inpossession of a simple (non-user-verifying) roaming authenticator, theycan use it to achieve a phishing-resistant account bootstrap, but willhave to also type a username and password. But if another user happensto have a more advanced user-verifying roaming authenticator, they willbe able to skip the password (and potentially even the username) stepduring account bootstrap.
The idea is that the relying party will create a credential on a roamingauthenticator, while being flexible as to whether that roamingauthenticator supports user verification and/or resident (akadiscoverable) credentials. If the authenticator supports userverification, the user will be able to skip the password login challengeduring account bootstrap. If the authenticator also supportsresident/discoverable credentials, the user will in addition be able toskip the identification step (typing the username, email address, orother user identifier). If the authenticator supports neither, then theuser canstill use the authenticator for a phishing-resistantaccount bootstrap, but will have to pass additional login challengesfirst (most likely username + password).
To achieve this, the relying party will not require user verification ora resident/discoverable credential during credential creation. Instead,you will set these to best-effort, or “preferred” mode (a feature onlyavailable in Level 2 of the webauthn specification). Note that you alsoneed to set thecredPropsextensionparameter to find out whether or not a resident/discoverable credentialwas created.
// Note that this example uses features only available// in Level 2 of the webauthn specification!// ---------------------------------------------------navigator.credentials.create({publicKey:{rp:{...},user:{...},challenge:...,pubKeyCredParams:{type:"public-key",alg:-7},excludeCredentials:[{//!!! other roaming authnrs already ontype:"public-key",// file for this userid:newUInt8Array([21,31,56,...]).buffer,transports:["usb","nfc"]},{type:"public-key",id:newUInt8Array([21,31,56,...]).buffer,transports:["internal","ble"]},{...}],authenticatorSelection:{authenticatorAttachment:"cross-platform",//!!!residentKey:"preferred",//!!!userVerification:"preferred"//!!!},extensions:{credProps:true,//!!!},}})
A note on attestation: We recommend that most relying parties not specify the attestation conveyance parameter
attestation
( thus defaulting to none), or instead explicitly use the valueindirect
. This guarantees the most streamlined user experience (platforms are likely to obtain consent from the user for other types of attestation conveyances, which likely results in a larger fraction of unsuccessful credential creations due to users canceling the creation).
Depending on whether a resident/discoverable credential was in factcreated, and whether the authenticator response indicates support foruser verification, the relying party can afterwards let the user knowwhat experience they should expect during subsequent account bootstraps,for example by telling them that they can use the “Sign in without apassword” feature mentioned inSigning in witha UVRA.
I.e., without any saved user state or credentials, e.g., cookies ordata in local storage containing (at least) the username or otherinformation about the user. Typically, account bootstrapping resultsin thecreation of saved user state on the user’s device, enablingthe user to later return via lower-friction flows.
Not all FIDO authenticators are user verification-capable, thoughall FIDO authenticators are at least capable oftesting for userpresence. The latter is a means of sensing that a user isat leastphysically present. For example, the blinking button on manysecurity keys is a user presence sensor. Touching it signalsauser is present, but does not distinguish among individuals as userverification does. User presence testing is appropriate formulti-step account bootstrapping where usersexplicitly supplymore than one authentication factor, e.g., their security key alongwith entering a password (i.e., “two-step verification”). However,user verification enablessingle-step account bootstrapping aswell as single-gesture reauthentication, thus reducing userfriction.
“Single-step” here refers to the fact that the user has to pass onlya single login challenge, not to the number of authenticationfactors. Single-step bootstrapping can be two-factor authentication,e.g., if the user has to confirm sign-in with their biometric(something they are) on their phone (something they have).
This combination is mostly applicable in enterprises that requirefrequent malware-resistant credential refreshes, but is not coveredin this guide.
This use case is not covered in this guide.
Although there are options to skip this step, which themselves useFIDO/webauthn APIs and UVRAs. We’ll discuss those inSigning-in with a UVRA.
Although there are exceptions: for example, in an enterprisecontext, users may not be able to create accounts themselves, andinstead need to rely on some other process to have the accountcreated for them.
We recommend that on this login challenge page, users can’t changetheir account identifier. Also, the login challenge should besomething that an unauthorized user of the device can’t pass.
Note that a relying partymay choose to treat signing-out as acomprehensive action and thus delete all references to the user’scredential id (if it has any). Such a relying party ought to treat asubsequent sign-in like an account bootstrap, and repeat the stepsexplained above inAuthenticating theUser andOpting into FIDO-basedReauthenticationat the time of the next sign-in.
We’ll discuss the use of user-verifying roaming authenticators forsingle-step account bootstrapping inSection 5.
I.e., where all users need to register some form of 2nd factorduring account creation or during their first sign-in.
We do not recommend that relying parties require a second factorduring reauthentication. Instead, you should see whether the user’splatform features a user-verifying FIDO platform authenticator, andemploy it, making reauthentication more user-friendly withoutsacrificing security.
There are ways to skip this step, which themselves use FIDO/webauthnAPIs. We’ll discuss thosebelow.
Though, depending upon the type of authenticator, they may need toprovide a PIN (which is locally processed by the platform OS andauthenticator).
Historically, we used the term “resident key” to refer to what willbe known as “discoverable credentials” in the upcoming WebAuthn L2and CTAP2.1 specs.