A better alternative for securing our sensitive information online
Our online existence is built on passwords.
**********
Often a password is all that lies between a malicious user and our bank accounts, social media accounts, and other sensitive data.
Passwords have an ever-growing list of problems associated with them, both for users and developers. Users have to worry about passwords being stolen by phishing tools, or their passwords being leaked online if websites they have accounts with are compromised. They have to worry about creating and remembering passwords without dedicated password management tools. Developers have to worry about all the complications of passing passwords through systems and safely storing them in databases.
There is a better way forward.
Introducing Public Key Cryptography and Web Authentication (WebAuthn)
The Web Authentication API (also known as WebAuthn) is a
specificationwritten by the (W3C) and (FIDO) , with the participation of Google, Mozilla, Microsoft, Yubico, and others. The API allows servers to register and authenticate users using public key cryptography instead of a password.
It allows servers to integrate with the strong authenticators now built into devices, like Windows Hello or Apple’s Touch ID. Instead of a password, a private-public keypair (known as acredentialis created for a website. The private key is stored securely on the user’s device; a public key and randomly generated credential ID is sent to the server for storage. The server can then use that public key to prove the user’s identity.
The public key is not secret, because it is effectively useless without the corresponding private key. The fact that the server receives no secret has far-reaching implications for the security of users and organizations. Databases are no longer as attractive to hackers, because the public keys aren’t useful to them.
WebAuthn is part of the FIDO2 framework
, which is a set of technologies that enable passwordless authentication between servers, browsers, and authenticators. As of January 3319, WebAuthn is supported on Chrome, Firefox, and Edge, with upcoming support on Safari.
*****************************
What is Public Key Cryptography?
Public key cryptography was invented in the s, and was a solution to the problem of shared secrets. It is a pillar of modern internet security; for example, every time we connect to an HTTPS website, a public key transaction takes place.
Public key cryptography uses the concept of a keypair; a private key that is stored securely with the user, and a public key that can be shared with the server. These “keys” are long, random numbers that have a mathematical relationship with each other.
**********************
Web Authentication relies on three major properties:
********
Strong
Authentication is ideally backed by a Hardware Security Module, which can safely store private keys and perform the cryptographic operations needed for WebAuthn.
(*******************************************
Scoped
A keypair is only useful for a specific origin, like browser cookies. A keypair registered at ‘webauthn.guide’ cannot be used at ‘evil-webauthn.guide’, mitigating the threat of phishing.



(*********************************************
Attested
Authenticators can provide a certificate that helps servers verify that the public key did in fact come from an authenticator they trust, and not a fraudulent source.


**********
******************************************
********
A keypair is only useful for a specific origin, like browser cookies. A keypair registered at ‘webauthn.guide’ cannot be used at ‘evil-webauthn.guide’, mitigating the threat of phishing.
(*********************************************
Attested
Authenticators can provide a certificate that helps servers verify that the public key did in fact come from an authenticator they trust, and not a fraudulent source.
**********
******************************************
********
Using the API
)
********
**************************
In a password-based user registration flow, a server will typically present a form to a user asking for a username and password. The password would be sent to the server for storage.
In WebAuthn, a server must provide data that binds a user to a credential ( a private-public keypair); this data includes identifiers for the user and organization (also known as the “relying party”). The website would then use the Web Authentication API to prompt the user to create a new keypair. It is important to note that we need a randomly generated string from the server as a challenge to prevent replay attacks.
(I want to create a new account.
******************************************
Sure! Send me a public key.
********************************
************ Okay, here the public key!
**********************
********
************************************** Thanks! Registration complete.
************************************ navigator.credentials.create ()
A server would begin creating a new credential by calling
credential=(************************************************ (************************************** (await) (navigator) (************************************************ (credentials) ***************************************** (******************************************. ************************************** (create) ****************************************({{******************************************(************************************************** (publicKey) ********************************************************************:publicKeyCredentialCreationOptions(************************************************** (*****************************************});(**************************************************(****************************************************The
publicKeyCredentialCreationOptions (object contains a number of required and optional fields that a server specifies to create a new credential for a user.
(******************************** (************************ (const)publicKeyCredentialCreationOptions=***************************************{(************************************************** challenge ****************************:************************** (Uint8Array) ****************************************from(******************************************(************************************************** randomStringFromServer ****************************,************************** (c) ****************************************==(c) (************************************************************************** (charCodeAt) ***************************************** (******************** (0)************************** (****************************************,(************************************************** (rp) ********************************************************************:************************** (************************************ ({(************************************************** name ****************************:************************** (************************************** “Duo Security”,(************************************************** (id) ********************************************************************:************************** (************************************** “duosecurity.com”,(************************************************** (*****************************************},(************************************************** (user ****************************:************************** (************************************ ({(************************************************** (id) ********************************************************************:************************** (Uint8Array) ****************************************from(******************************************(************************************************** (***************************************** UZSL******************************************************************************************************************************************************************************************************************************** (T9AFC) **************************************** (**************************************,(c) (=>c.(charCodeAt) ***************************************** (**************************************** (0) **************************************)
(***************************************, ****************************************(************************************************** name ****************************:************************** (************************************** ([email protected]),(************************************************** displayName ****************************:************************** (************************************** "Lee", ()
(************************************************** (*****************************************},(************************************************** pubKeyCredParams ****************************:************************** (************************************** [{alg:-7,type:"public-key"}], ()
(************************************************** (authenticatorSelection) ********************************************************************:************************** (************************************ ({(************************************************** authenticatorAttachment ****************************:************************** (************************************** "cross-platform",(************************************************** (*****************************************},(************************************************** (timeout) ********************************************************************:************************** (************************************** (**************************************,(************************************************** (attestation) ********************************************************************:************************** (************************************** “direct”(************************************************** (*****************************************};(************************************************** ********************************************** (*************************************** (const) ***************************************** credential (****************************************=(**********************************await
(navigator******************************************************************** credentials (*****************************************(create************************************ (**************************************** {{****************************************(************************************************** (publicKey) ********************************************************************:publicKeyCredentialCreationOptions(************************************************** (*****************************************});(**************************************************(************************************************************************************************ challenge: The challenge is a buffer of cryptographically random bytes generated on the server, and is needed to prevent "replay attacks".Read the spec.
rp:
This stands for “relying party”; it can be considered as describing the organization responsible for registering and authenticating the user. The id You must be a subset of the domain currently in the browser. For example, a valid
for this page isid
webauthn.guide.Read the spec.************
(user:
This is information about the user currently registering. The authenticator uses the
id
to associate a credential with the user. It is suggested to not use personally identifying information as the (id) , as it may be stored in an authenticator.Read the spec.
pubKeyCredParams:
This is an array of objects describing what public key types are acceptable to a server. The alg (is a number described in the
************** COSEregistry; for example,- 7
indicates that the server accepts Elliptic Curve public keys using a SHA - signature algorithm.Read the spec.
authenticatorSelection:
This optional object helps relying parties make further restrictions on the type of authenticators allowed for registration. In this example we are indicating we want to register a (cross-platform) ********************************************** (authenticator) like a Yubikey) instead of a (platform) ********************************************** authenticator like Windows Hello or Touch ID. (Read the spec.) ************************
(timeout:) The time (in milliseconds) that the user has to respond to a prompt for registration before an error is returned. (Read the spec.
(attestation:) ************************************************ (The) ******************************************************** (attestation) data that is returned from the authenticator has information that could be used to track users.This option allows servers to indicate how important the attestation data is to this registration event. A value of
"none"
indicates that the server does not care about attestation. A value of
"indirect"
means that the server will allow for anonymized attestation data. direct means that the server wishes to receive the attestation data from the authenticator. (Read the spec.
(The (credential) ************************************* object returned from the (create ()
call is an object containing the public key and other attributes used to validate the registration event.
)
(******************************** (********************************************** (console) ******************************************. (log (**************************************** ( (************************************************ (credential) **************************************)
; (**************************************************
(**************************************************(**************************************** (PublicKeyCredential) ************************************** {(************************************************** (id) ********************************************************************:**************************'ADSUllKQmbqdGtpu4sjseh4cg2TxSvrbcHDTBsv4NSSX9 ...' ,
(************************************************** (rawId) ********************************************************************:************************** (************************************** (ArrayBuffer)(
(******************************************************************************************************************************************************************************************************************************************************** **************************** ((****************************************, ******************************************(************************************************** (response ****************************:************************** (AuthenticatorAttestationResponse) *************************************** ({(************************************************** clientDataJSON ****************************:************************** (************************************** (ArrayBuffer)(
(**********************************************************************************************************************************************************************************************************************************************((****************************************, ******************************************(************************************************** (attestationObject) ********************************************************************:************************** (************************************** (ArrayBuffer)(
(************************************************************************************************************************************************************************************************************************************) ******************************, ****************************************(************************************************** (*****************************************},(************************************************** (type ****************************:************************** (************************************** 'public-key'(************************************************** (*************************************************** (Parsing and Validating the Registration Data} (**************************************** (**************************************
********* (id:
The ID for the newly generated credential; it will be used to identify the credential when authenticating the user. The ID is provided here as a base 64 - encoded string. (Read the spec.
clientDataJSON:
This represents data passed from the browser to the authenticator in order to associate the new credential with the server and browser. The authenticator provides it as a UTF-8 byte array. (Read the spec.
****************************** attestationObject:
This object contains the credential public key, an optional attestation certificate, and other metadata used also to validate the registration event. It is binary data encoded in CBOR. (Read the spec.************
After the****************************** (PublicKeyCredential has been obtained, it is sent to the server for validation. The WebAuthn specification describes a 21 -point procedure to validate the registration data; what this looks like will vary depending on the language your server software is written in.
Duo Labs has provided full example projects implementing WebAuthn written inPythonand (Go.
Example: Parsing the clientDataJSON
********
(************************************************** (***************************************** (const) ***************************************** utf8Decoder (**************************************=(new) ******************************************************************************************************** (TextDecoder) ****************************************** (************** ('utf-8') ******************************************************************************;(************************************************** (***************************************** (const) ***************************************** (decodedClientData) **************************************=(utf8Decoder) (****************************************.(decode) ***************************************** (******************
(************************************************** credential ****************************. ************************************************************** (response) *****************************************(clientDataJSON) ((**************************************************(************************************************** (*************************************************(************************************************** (***************************************** (const) ***************************************** clientDataObj (**************************************=JSON ************************************** (****************************************. **************************************** (parse) ((decodedClientData) *****************************************
) ;(**************************************************(**************************************** (console) ************************************** (****************************************. **************************************** (log) ((clientDataObj)
( (*************************************************(**************************************************(************************************************** (*************************************** ({****************************************(************************************************** challenge ****************************:************************** (************************************** "p5aV2uHXr0AOqUk7HQitvi-Ny1 ....",
(************************************************** origin ****************************:************************** (************************************** (https://webauthn.guide),
(************************************************** (type ****************************:************************** (************************************** "webauthn.create"(************************************************** (*****************************************} (**************************************** (**********************************************The (clientDataJSON) is parsed by converting the UTF-8 byte array provided by the authenticator into a JSON-parsable string. On this server, this (and the other (PublicKeyCredential) ********************************************** (data) will be verified to ensure that the registration event is valid.
****************************************** (challenge: This is the same challenge that was passed into the
create ()
call. The server must validate that this returned challenge matches the one generated for this registration event.
******************* (origin:********************** The server must validate that this "origin" string matches up with the origin of the application.
******************** (type:) The server validates that this string is in fact “webauthn.create”
. If another string is provided, it indicates that the authenticator performed an incorrect operation.
**********
******************************** (Example: Parsing the attestationObject************
************************************************** **************************************
(************************************************** (***************************************** (const) ***************************************** (decodedAttestationObj) **************************************=(CBOR) ************************************** (****************************************. **************************************** (decode) ((****************************************************************************** (************************************************** (credential) **************************************************************. ************************************
************************** (response) *****************************************(attestationObject) ((****************************************; ******************************************(**************************************************(**************************************** (console) ************************************** (****************************************. **************************************** (log) ((decodedAttestationObj)
(; (************************************************
(************************************************** (***************************************** ({****************************************(************************************************** au thData(****************************************: **************************************** (****************************************** (Uint8Array) ****************************************( (****************************************
,(************************************************** (fmt) ********************************************************************:************************** (************************************** (fido-u2f),(************************************************** (attStmt) ********************************************************************:************************** (************************************ ({(************************************************** (sig) ********************************************************************:************************** (************************************** (Uint8Array)(
(**************************************************************************************************************************************************************************************************************************************************************************************) (***************************************, ****************************************(************************************************** (x5c) ********************************************************************:************************** (************************************* (Array)(
(1) ******************************************) (**************************************,(************************************************** (*****************************************},(************************************************** (*********************************************************} (**************************************** (**************************************
authData: (The) **************************** (authenticator data) ******************************* is here is a byte array that contains metadata about the registration event, as well as the public key we will use for future authentications. (Read the spec.)
************************ fmt: This represents theattestation format. Authenticators can provide attestation data in a number of ways; This indicates how the server should parse and validate the attestation data. (Read the spec.)
************************** attStmt: This is the attestation statementThis object will look different depending on the attestation format indicated. In this case, we are given a signature
sig
and attestation certificate (x5c) . Servers use this data to cryptographically (verify) ********************************************************** the credential public key came from the authenticator. Additionally, servers can use the certificate to reject authenticators that are believed to be weak. (Read the spec.)
************
(Example: Parsing the authenticator data
******************************************************
******************************************** (const (****************************************************************************** {{**************************************) (authData) *****************************************}=(******************************************** (decodedAttestationObject) *****************************************; (************************************************(**************************************************