This article continues from our previous blog on an Introduction to FIDO & WebAuthn. As a quick refresh, WebAuthn is short for Web Authentication and FIDO is short for Fast IDentity Online.
I’ll cover the WebAuthn API in more detail and share my experiences from working with the API. Ubisecure is also introducing an interactive WebAuthn API testing tool you can use to explore the API yourself.
The end of this article covers a couple of use cases on a higher level.
WebAuthn API
The WebAuthn API is specified by Web Authentication: An API for accessing Public Key Credentials published by W3C. The status of this specification was recently (March 2019) updated to W3C Recommendation, which means the specification is complete and no major changes are expected.
On the surface the API looks quite simple with only three relevant methods:
- credentials.create()
Registration use case - credentials.get()
Authentication use case - PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
Feature discovery
It turns out the WebAuthn API is an extension of another API: Credential Management Level 1. In practice, this doesn’t matter much but some of the terminology and naming conventions are inherited from this parent specification.
WebAuthn Registration
Registration request syntax
The registration request is specified by PublicKeyCredentialCreationOptions. The top-level members of this structure are:
- rp.id, rp.name, rp.icon
Information about the relying-party or the application where rp.id by default has value of location.host
It is possible to set rp.id to the value of the parent domain to register credentials for a common domain – for example, if the application is on login.example.com then rp.id can be example.com - user.id, user.name, user.displayName, user.icon
Information about the user registering
The user.id value appears as userHandle member of Authentication Response
User information helps the username-less use case, where this information helps them choose from multiple credentials - challenge
Cryptographic challenge with enough randomness to allow detecting replay - pubKeyCredParams
List of cryptographic algorithms supported by the application
COSE identifiers are used, where -7 is ES256 and -257 is RS256 - excludeCredentials
Lists credentials already registered for the user. The intent is to prevent registering multiple credentials on a single authenticator. Windows Hello, for example, appears to replace existing credentials. - authenticatorSelection
Controls what types of authenticators are accepted for registration.
If more than one authenticator match this criteria then the user is presented with a menu to choose from.- authenticatorAttachment
Select either a platform or portable authenticator - requireResidentKey
Select an authenticator with resident credential storage - userVerification
Select an authenticator that implements user verification
- authenticatorAttachment
- attestation
Request authenticator attestation. In this article I’m not covering processing attestations.
The isUserVerifyingPlatformAuthententicator method can be used to detect if a platform authenticator that implements user verification exists on the user agent device. This allows the application to improve user experience by only displaying options in the user interface that are sure to exist.
Registration request example
An example registration request with a minimal set of parameters
{ "publicKey": { "rp": { "name": "https://psteniusubi.github.io" }, "user": { "name": "[email protected]", "displayName": "Hello Example", "id": "aGVsbG9AZXhhbXBsZS5jb20" }, "challenge": "yGvVFCug1QLmaW4OnIYw7JONQP7XDSDNZ3SELT0PBhI", "pubKeyCredParams": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 } ] } }
Registration response syntax
The registration response is specified by PublicKeyCredential and AuthenticatorAttestationResponse. Response processing rules are specified by Registering a New Credential.
The response is fairly complex with multiple nested data structures using various text and binary encodings such as JSON, CBOR, COSE and even ASN.1.
The top-level members of PublicKeyCredential are
- type = “public-key”
Identifies the response as PublicKeyCredential - id, rawId
Credential identifier (same value, two different encodings) - response
Contains an AuthenticatorAttestationResponse object
The top-level members of AuthenticatorAttestationResponse are
- clientDataJSON
JSON encoded parameters from registration request. Allows correlating request and response - attestationObject
CBOR encoded attestation statement and authenticator data
Contents of clientDataJSON
- type = “webauthn.create”
Identifies this as the response to the registration request - challenge
From the registration request, for correlating messages and to detect replay - origin
Value of location.origin on the web page where request originated - tokenBinding
Optional indication of token binding support
Contents of attestationObject
- fmt = “none”
Format of attestation statement. “none” if attestation was not requested - attStmt
Attestation statement. Empty if attestation was not requested - authData
Binary encoded authenticator data
Contents of authData
- rpIdHash
SHA 256 hash of rp.id parameter from request - flags
Bit flags indicating authenticator capabilities (user present, user verified) and contents of authData structure (credential data and/or extension present) - signCount
Signature counter. Always 0 in response to registration - attestedCredentialData
- aaguid
128 bit value, identifies authenticator type. May be zero
Windows Hello aaguid values https://docs.microsoft.com/en-us/microsoft-edge/dev-guide/windows-integration/web-authentication - credentialId
Credential identifier, same as id and rawId top-level parameters - credentialPublicKey
COSE encoded EC or RSA public key
- aaguid
Registration response example
An example registration response
{ "id": "9Y_H6NruEEvScYq3NeRJP-28PL9omSMkfC6s2EuTmj4", "type": "public-key", "rawId": "9Y_H6NruEEvScYq3NeRJP-28PL9omSMkfC6s2EuTmj4", "response": { "clientDataJSON": "ew0KCSJ0eXBlIiA6ICJ3ZWJhdXRobi5jcmVhdGUiLA0KCSJjaGFsbGVuZ2UiIDogInlHdlZGQ3VnMVFMbWFXNE9uSVl3N0pPTlFQN1hEU0ROWjNTRUxUMFBCaEkiLA0KCSJvcmlnaW4iIDogImh0dHBzOi8vcHN0ZW5pdXN1YmkuZ2l0aHViLmlvIiwNCgkidG9rZW5CaW5kaW5nIiA6IA0KCXsNCgkJInN0YXR1cyIgOiAic3VwcG9ydGVkIg0KCX0NCn0", "attestationObject": "o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVkBZyzXk8-gtBjLvw6oUiKGB9npezM9TbCkEBd2ava7jHVRRQAAAABgKLAXsdRMArSzr82vyWuyACD1j8fo2u4QS9Jxirc15Ek_7bw8v2iZIyR8LqzYS5OaPqQBAwM5AQAgWQEA0Y2rM1KvYnVmRX-MHi2c3kdBNssnaTg_TzfoBRrJjw3PnV4-hMvPRXnDKxy4W4Ka2UZrfrJ9guTndbpcK6yVcBLNQoDEhTNrf2OuSUaUKJ9dw1GPFrzCkWgq_C8ZdkFCWbNylHj1w3E0yJMOAHnFX6D-9WyT6fLEXhTuJYE8v4ugLO_YHRIPyxSahophXlczhkGeJHg97unr4xKJjC2ssuAnpM2nvYTd2yV_VOe4x3Vrpbj40eItEt0s5hCuA5ivxI4VRo07MbWWvR910a13d_h-p-MJA5DBbHCF87Ee_N6z4UKWtE8aepI1purzb0_iVjKnt_cyTTtIJHcCKu5qvSFDAQAB" } }
Decoded clientDataJSON
{ "type": "webauthn.create", "challenge": "yGvVFCug1QLmaW4OnIYw7JONQP7XDSDNZ3SELT0PBhI", "origin": "https://psteniusubi.github.io", "tokenBinding": { "status": "supported" } }
Decoded attestationObject
{ "fmt": "none", "attStmt": {}, "authData": "LNeTz6C0GMu_DqhSIoYH2el7Mz1NsKQQF3Zq9ruMdVFFAAAAAGAosBex1EwCtLOvza_Ja7IAIPWPx-ja7hBL0nGKtzXkST_tvDy_aJkjJHwurNhLk5o-pAEDAzkBACBZAQDRjaszUq9idWZFf4weLZzeR0E2yydpOD9PN-gFGsmPDc-dXj6Ey89FecMrHLhbgprZRmt-sn2C5Od1ulwrrJVwEs1CgMSFM2t_Y65JRpQon13DUY8WvMKRaCr8Lxl2QUJZs3KUePXDcTTIkw4AecVfoP71bJPp8sReFO4lgTy_i6As79gdEg_LFJqGimFeVzOGQZ4keD3u6evjEomMLayy4Cekzae9hN3bJX9U57jHdWuluPjR4i0S3SzmEK4DmK_EjhVGjTsxtZa9H3XRrXd3-H6n4wkDkMFscIXzsR783rPhQpa0Txp6kjWm6vNvT-JWMqe39zJNO0gkdwIq7mq9IUMBAAE" }
Decoded authData
{ "rpIdHash": "LNeTz6C0GMu_DqhSIoYH2el7Mz1NsKQQF3Zq9ruMdVE", "flags": { "value": 69, "up": true, "uv": true, "at": true, "ed": false }, "signCount": 0, "attestedCredentialData": { "aaguid": "YCiwF7HUTAK0s6_Nr8lrsg", "credentialId": "9Y_H6NruEEvScYq3NeRJP-28PL9omSMkfC6s2EuTmj4", "credentialPublicKey": "pAEDAzkBACBZAQDRjaszUq9idWZFf4weLZzeR0E2yydpOD9PN-gFGsmPDc-dXj6Ey89FecMrHLhbgprZRmt-sn2C5Od1ulwrrJVwEs1CgMSFM2t_Y65JRpQon13DUY8WvMKRaCr8Lxl2QUJZs3KUePXDcTTIkw4AecVfoP71bJPp8sReFO4lgTy_i6As79gdEg_LFJqGimFeVzOGQZ4keD3u6evjEomMLayy4Cekzae9hN3bJX9U57jHdWuluPjR4i0S3SzmEK4DmK_EjhVGjTsxtZa9H3XRrXd3-H6n4wkDkMFscIXzsR783rPhQpa0Txp6kjWm6vNvT-JWMqe39zJNO0gkdwIq7mq9IUMBAAE" } }
Decoded credentialPublicKey
{ "kty": "RSA", "alg": "RS256", "n": "0Y2rM1KvYnVmRX-MHi2c3kdBNssnaTg_TzfoBRrJjw3PnV4-hMvPRXnDKxy4W4Ka2UZrfrJ9guTndbpcK6yVcBLNQoDEhTNrf2OuSUaUKJ9dw1GPFrzCkWgq_C8ZdkFCWbNylHj1w3E0yJMOAHnFX6D-9WyT6fLEXhTuJYE8v4ugLO_YHRIPyxSahophXlczhkGeJHg97unr4xKJjC2ssuAnpM2nvYTd2yV_VOe4x3Vrpbj40eItEt0s5hCuA5ivxI4VRo07MbWWvR910a13d_h-p-MJA5DBbHCF87Ee_N6z4UKWtE8aepI1purzb0_iVjKnt_cyTTtIJHcCKu5qvQ", "e": "AQAB" }
WebAuthn Authentication
Authentication request syntax
The authentication request is specified by PublicKeyCredentialRequestOptions. The top-level members of this structure are
- challenge
Cryptograhic challenge with enough randomness to allow detecting replay - rpId
Information about the relying-party. Must match the value of rp.id from registration request - allowCredentials
List of credentials registered for the user. Not set for username-less use case. Must be used with authenticators that implement client side storage model.
If more than one authenticator match this criteria then user is presented with a menu to choose from. - userVerification
What level of user verification is required for authentication
Authentication request example
An example authentication request with a minimal set of parameters
{ "publicKey": { "challenge": "3RyGpNPHTqDdJ3LSEhSv_pWydPcNrrSAXWuRta_9K8g" } }
Authentication response syntax
The registration response is specified by PublicKeyCredential and AuthenticatorAssertionResponse. Response processing rules are specified by Verifying an Authentication Assertion.
The top-level members of PublicKeyCredential are
- type = “public-key”
Identifies the response as PublicKeyCredential - id, rawId
Credential identifeier (same value, two different encodings) - response
Contains an AuthenticatorAssertionResponse object
The top-level members of AuthenticatorAssertionResponse are
- clientDataJSON
JSON encoded parameters from authentication request. Allows correlating request and response. - authenticatorData
CBOR encoded authenticator data - signature
Digital signature of clientDataJSON and authenticatorData. Verified with credentialPublicKey from registration response.
For EC algorithm the signature value is ASN.1 encoded - userHandle
user.id value that was used while registering this credentials. May be zero
Contents of clientDataJSON
- type = “webauthn.get”
Identifies this as response to authentication request - challenge
From registration request, for correlating messages and to detect replay - origin
Value of location.origin on the web page where request originated - tokenBinding
Optional indication of token binding support
Contents of authenticatorData
- rpIdHash
SHA 256 hash of rpId parameter from request - flags
Bit flags indicating authenticator capabilities (user present, user verified) and contents of authData structure (extension present) - signCount
Signature counter. Application may use this field to detect duplicated credentials
Authentication response example
{ "id": "9Y_H6NruEEvScYq3NeRJP-28PL9omSMkfC6s2EuTmj4", "type": "public-key", "rawId": "9Y_H6NruEEvScYq3NeRJP-28PL9omSMkfC6s2EuTmj4", "response": { "clientDataJSON": "ew0KCSJ0eXBlIiA6ICJ3ZWJhdXRobi5nZXQiLA0KCSJjaGFsbGVuZ2UiIDogIjNSeUdwTlBIVHFEZEozTFNFaFN2X3BXeWRQY05yclNBWFd1UnRhXzlLOGciLA0KCSJvcmlnaW4iIDogImh0dHBzOi8vcHN0ZW5pdXN1YmkuZ2l0aHViLmlvIiwNCgkidG9rZW5CaW5kaW5nIiA6IA0KCXsNCgkJInN0YXR1cyIgOiAic3VwcG9ydGVkIg0KCX0NCn0", "authenticatorData": "LNeTz6C0GMu_DqhSIoYH2el7Mz1NsKQQF3Zq9ruMdVEFAAAAAQ", "signature": "UYkZ_1nlyV8L5ByJ8yGhIjv8WSkfuFKG00pGwy_HFrDRo1FIbYPfMm_KZ01h0OhnHAEDlEuvvp-DAoHNtaP2KAesP-MTKaw4qhTvuEqdQ4uTjAtrwwLg7OsgE32FSVWLPiMGbowFrPEZaGLYtv9zk5lYqCWbWpAwN20kWmBCDpub2hbB4VlhECcne0804-Bd7tDfc89qL0Uukfdf7zjiX6YAS5P6Bvk-gug4Gx8YatvQU7PpyKZvb0oNKHQxwej-iQqx9Nsaen4F9Xcg_XLNFH18uf3hNoIAqylVQjkZxsMLob7lQCKrP9aLYyjl2-IZO9i6ZiM8RNiZEy_DAK4DvA", "userHandle": "aGVsbG9AZXhhbXBsZS5jb20" } }
Decoded clientDataJSON
{ "type": "webauthn.get", "challenge": "3RyGpNPHTqDdJ3LSEhSv_pWydPcNrrSAXWuRta_9K8g", "origin": "https://psteniusubi.github.io", "tokenBinding": { "status": "supported" } }
Decoded authenticatorData
{ "rpIdHash": "LNeTz6C0GMu_DqhSIoYH2el7Mz1NsKQQF3Zq9ruMdVE", "flags": { "value": 5, "up": true, "uv": true, "at": false, "ed": false }, "signCount": 1 }
WebAuthn testing tool
The testing tool is implemented as a browser-based application. This tool keeps registered credentials in the browser’s local storage. There are three different pages:
- credential-create.html
For the registration use case. Use drop-down menus to test with different parameters of registration request. - credential-get.html
For the authentication use case. Use drop-down menus to test with different parameters of authentication request. - credential-edit.html
To manage credentials saved by this tool in the browser’s local storage. It is possible to copy credentials across browsers and devices.
The testing tool source code is on GitHub https://github.com/psteniusubi/webauthn-tester.
WebAuthn testing tool requirements
Windows
On Windows 10 version 1809 and later you need to activate Windows Hello by clicking here ms-settings:signinoptions. Your computer does not need any special hardware as it’s possible to activate Windows Hello with a software authenticator and PIN code protection.
Android
On mobile phones with recent versions of Android, everything should be ready to run.
Instructions
Registration
Navigate to credential-create.html
Click credentials.create() button
Authentication
Navigate to credential-get.html
Click credentials.get() button
Note about Chrome and new Chromium based Edge
On a Chrome browser you may see this error
NotSupportedError: Resident credentials or empty 'allowCredentials' lists are not supported at this time.
To work around this you need to choose a previously registered credential from the allowCredentials list
Registration use cases
Registering multiple authenticators
Registering multiple authenticators for an account is useful for many reasons. A user should be allowed to register a platform authenticator on each device the user uses. The user also needs to register one or more portable authenticators to allow registering new devices or as backup keys for account recovery purposes.
The process is complex and the application should guide the user to avoid mistakes. The application should not let users register the wrong type of authenticator or create multiple credentials on a single authenticator.
Registering a portable authenticator
If the user has not registered any authenticators, then the user needs to sign in with a password or create a new account.
If the user has an existing account then the user needs to sign in with a portable authenticator. For an existing account excludeCredentials is set to list of existing credentials to prevent re-using an existing authenticator.
The application guides the user to register a portable authenticator by setting authenticatorAttachment property.
In this example, the user has already registered another portable authenticator which is listed in excludeCredentials.
{ "publicKey": { "rp": { "name": "https://psteniusubi.github.io" }, "user": { "name": "[email protected]", "displayName": "Hello Example", "id": "aGVsbG9AZXhhbXBsZS5jb20" }, "challenge": "im0sLy6nVAl0loRnDbpZ2ES1W9cAAY7Xlqnw55ixNR4", "pubKeyCredParams": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 } ], "excludeCredentials": [ { "id": "eAQuVb1k_vKF7MYFbmkfHMEuqlASg1Xz_fQaK-O2U5M", "type": "public-key" } ], "authenticatorSelection": { "authenticatorAttachment": "cross-platform" } } }
Sign in with portable authenticator
To register a new device or to register a new portable authenticator, the user first authenticates with one of the registered portable authenticators. The application sets allowCredentials to list all registered portable authenticators.
{ "publicKey": { "challenge": "iqBhlGkxkZWkZdkG5H6Q2C65DUfD18cYEXYPBXsEjcQ", "allowCredentials": [ { "id": "eAQuVb1k_vKF7MYFbmkfHMEuqlASg1Xz_fQaK-O2U5M", "type": "public-key" } ] } }
Registering a new device
The user first signs in with a portable authenticator, then the application guides the user to register a new platform authenticator that supports user verification. The application sets excludeCredentials to list of all authenticators to prevent re-using an existing authenticator, and also sets authenticatorAttachment and userVerification.
{ "publicKey": { "rp": { "name": "https://psteniusubi.github.io" }, "user": { "name": "[email protected]", "displayName": "Hello Example", "id": "aGVsbG9AZXhhbXBsZS5jb20" }, "challenge": "w9tfGIKwkvw_JnIVseHd6sKXatSQJ7tkPrGTNQOmczE", "pubKeyCredParams": [ { "type": "public-key", "alg": -7 }, { "type": "public-key", "alg": -257 } ], "excludeCredentials": [ { "id": "eAQuVb1k_vKF7MYFbmkfHMEuqlASg1Xz_fQaK-O2U5M", "type": "public-key" } ], "authenticatorSelection": { "authenticatorAttachment": "platform", "userVerification": "required" } } }
Authentication use cases
What authentication use case variations can you implement with WebAuthn? The difference in use cases is related to what information the user needs to provide and what authentication factors are considered.
The available factors are:
- Something you know
Password of your user account
PIN code used to unlock FIDO authenticator - Something you have
Laptop or mobile phone with a platform FIDO authenticator
Cross-platform FIDO authenticator, such as a USB token - Something you are
Biometric gesture, such as fingerprint scan, used to unlock a FIDO authenticator
An authentication use case based on a combination of any two factors is generally considered secure.
With WebAuthn the typical use cases are controlled with authentication request parameters allowCredentials and userVerification.
Universal 2nd factor (U2F)
U2F is probably more common and better known in context of FIDO 1.0. However this use case is still valid with FIDO 2.0 and WebAuthn.
With this use case you need to provide both your username and password to initially identify yourself, so the ‘something you know’ factor is the password of your user account. The second factor, ‘something you have’, is the FIDO authenticator.
The application asks for username and password, then asks to authenticate with an authenticator that tests for user presence.
The combination of authentication factors is something you know and something you have.
Authentication request parameters
- allowCredentials
Set to list of credentials bound to user account - userVerification = “discouraged”
A single-factor FIDO authenticator is sufficient
Example
{ "publicKey": { "challenge": "65KV2ArKNS5i2wEqqoxzkkD6500xDOK4xUA_wBktIsk", "allowCredentials": [ { "id": "9Y_H6NruEEvScYq3NeRJP-28PL9omSMkfC6s2EuTmj4", "type": "public-key" } ], "userVerification": "discouraged" } }
Password-less authentication
With this use case you need to provide your username but the password of your user account is not needed. Instead, a FIDO authenticator with user verification is used.
The application asks for username only, then asks to authenticate with an authenticator bound to the user account that requires user verification.
The combination of authentication factors is either ‘something you know’ and ‘something you have’ (PIN code protected authenticator), or ‘something you are’ and ‘something you have’ (Biometric authenticator).
Authentication request parameters
- allowCredentials
Set to list of credentials bound to user account - userVerification = “required”
A two-factor FIDO authenticator is required
Example
{ "publicKey": { "challenge": "g4WfiNib0VwcyMlGfYUX1E-Rv1stkMYqnyqhHJR6e28", "allowCredentials": [ { "id": "9Y_H6NruEEvScYq3NeRJP-28PL9omSMkfC6s2EuTmj4", "type": "public-key" } ], "userVerification": "required" } }
Username-less authentication
With this use case you don’t need to initially provide any information. The application does not ask for username or password, instead the application asks to authenticate with any authenticator present on the user’s device that requires user verification. If you have registered more than one FIDO credential with this application then you are presented with a menu to choose from, so you don’t need to type in your username but get to choose from a menu.
Windows Hello credential selection menu
This is a slight extension of the Password-less use case and only works with authenticators with resident keys, where the credential is stored embedded in the authenticator.
The combination of authentication factors is either ‘something you know’ and ‘something you have’ (PIN code protected authenticator), or ‘something you are’ and ‘something you have’ (Biometric authenticator).
Authentication request parameters
- allowCredentials
Not set because the user is not initially identified - userVerification = “required”
A two-factor FIDO authenticator is required
Example
{ "publicKey": { "challenge": "TUEY64516YPw2KYYkKmnJ-SA3hi3lCwvL5RL1Lln6nI", "userVerification": "required" } }
Findings
Terminology
The terminology around FIDO and WebAuthn can be a bit confusing.
- U2F – Universal 2nd Factor
- 2FA – Two Factor Authentication
- MFA – Multi Factor Authentication
- 2SV – Two Step Verification
(All of these three-letter acronyms are basically the same thing: authentication with more than one factor. I prefer MFA as it also stands for authentication with all three factors.) - Security Key, Security Token or Security Fob?
What is the name of that tiny USB connector size thing that looks like a memory stick, but holds your credentials? - Password-less and Username-less
Names for slight variations of MFA. - FIDO 1, FIDO 2 and WebAuthn
FIDO 1 and FIDO 2 are quite different so there is a reason to separate. Hopefully FIDO (with no number) will soon be understood as FIDO 2 and WebAuthn.
Different shapes of security keys
Platform support
Many platforms and browsers have already implemented support. The remaining are quickly catching up. Things are moving fast so check the latest status from platform vendors.
Windows
The Windows 1809 update added WebAuthn and Windows Hello to the Edge Browser. The big surprise is that the next update in Windows 1903 adds Windows Hello to Chrome and Firefox too.
Chrome and Firefox
Before Windows 1903 these browsers only supported cross-platform authenticators, for example USB connected tokens.
Chrome on Windows before 1903
Android
Chrome on Android has had support for WebAuthn since last year.
Google recently announced that a Bluetooth connected Android device will soon work as a cross-platform authenticator for Chrome on Windows.
OS X and iOS
Apple has released preview versions of Safari with WebAuthn.
Chrome has support for WebAuthn and Touch ID on OS X.
Conclusions
Is WebAuthn ready for the general public? The specification is complete. With Safari browser support in the pipeline, platform support is becoming available to most users. The recent announcement from Google, about enabling Android phones as WebAuthn portable authenticators, will increase access to convenient authenticators even further.
Can WebAuthn replace your password? That depends on what we expect ‘replace password’ to mean. Your application could simply use WebAuthn authentication as the most frequent and convenient authentication method, but still keep passwords as a fallback. Or you can aim at significantly improving security and remove passwords completely.
The first alternative does not completely remove passwords from user accounts but allows using a WebAuthn authenticator as an option to the account password. During sign in, the application allows users to choose between username-less, password-less or traditional username and password authentication methods. This improves the sign in experience but does not improve security much, as the risky password option remains available as a fallback.
Microsoft has enabled username-less sign in as an option on Windows Live.
If you want to improve security and completely remove passwords from user accounts then your application also needs to consider account recovery and registration of new devices. You cannot fall back to a significantly less secure method such as a password. To allow account recovery in case of a lost or damaged authenticator, you need to make sure your users register at least two different physical authenticators.
The Google Advanced Protection Program requires two or more authenticators.
Probably the simplest integration is to not try to replace the password at all, but implement the U2F use case and add WebAuthn as one more option for second factor authentication. WebAuthn could be more convenient than some other options such as mobile authenticator apps or passwords sent as text messages.
Google allows you to add a portable WebAuthn authenticator as a second factor to your normal Google account.
When considering implementing WebAuthn it is probably a good time to again re-consider whether to build or buy a IAM solution. WebAuthn is a new and important technology in the IAM space that improves both usability and overall security, but comes with its own set of complexities.
About The Author: Petteri Stenius
Principal Scientist at Ubisecure
More posts by Petteri Stenius