HYPR SDK for FIDO2 Browser

HYPR SDK FIDO2 and WebAuthn

HYPR SDK for FIDO2 Browser provides an abstraction layer to the FIDO2 WebAuthn APIs for a simpler developer experience.

Getting HYPR SDK for FIDO2 Browser

Ask your HYPR support representative for HYPR SDK for FIDO2 Browser. This will be a JavaScript file deliverable called hyprfido2sdk.js.

This sample has the entire SDK in a single line of minified JavaScript:

function base64ToArrayBuffer(r){let e=atob(r),n=e.length,t=new Uint8Array(n);for(let r=0;r<n;r++)t[r]=e.charCodeAt(r);return t.buffer}function bufferToString(r){return new Uint8Array(r).reduce((r,e)=>r+String.fromCodePoint(e),"")}function toBase64URL(r){return r=(r=(r=r.split("=")[0]).replace(/\+/g,"-")).replace(/\//g,"_")}function fromBase64URL(r){var e=(r=r.replace(/-/g,"+").replace(/_/g,"/")).length%4;if(e){if(1===e)throw new Error("InvalidLengthError: Input base64url string is the wrong length to determine padding");r+=new Array(5-e).join("=")}return r}
const HYPRFido2Client={createAttestationOptions:function(e,t,n="platform",a="required",r=!1,i="direct"){return{username:e,displayName:t,authenticatorSelection:{authenticatorAttachment:n,userVerification:a,requireResidentKey:r},attestation:i}},createAssertionOptions:function(e,t="preferred",n="platform"){return{username:e,userVerification:t,authenticatorSelection:{authenticatorAttachment:n}}},createFido2Credential:function(e,t,n=!0){function a(e){return{id:e.id,rawId:toBase64URL(btoa(bufferToString(e.rawId))),type:"public-key",response:{clientDataJSON:toBase64URL(btoa(bufferToString(e.response.clientDataJSON))),attestationObject:toBase64URL(btoa(bufferToString(e.response.attestationObject)))}}}if(HYPRFido2Client.checkWebAuthnSupport(t))"platform"===e.authenticatorSelection.authenticatorAttachment?PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().then(function(r){if(r)navigator.credentials.create(HYPRFido2Client.makePublicKey(e,n)).then(e=>{t(null,a(e))}).catch(e=>{console.error("Error processing credential create request for WebAuthn with code: "+e.code+" and message: "+e.message+" and name: "+e.name),t(e)});else{const e=new Error("Cannot continue since WebAuthn Platform Authentication is not available on this browser and client");e.name="WebAuthnPlatformUnavailable",t(e)}}).catch(e=>{console.error("Error processing credential create request for WebAuthn with code: "+e.code+" and message: "+e.message+" and name: "+e.name),t(e)}):navigator.credentials.create(HYPRFido2Client.makePublicKey(e)).then(e=>{t(null,a(e))}).catch(e=>{console.error("Error processing credential GET request for WebAuthn with code: "+e.code+" and message: "+e.message+" and name: "+e.name),t(e)});else{const e=new Error("Cannot continue since WebAuthn is not available on this browser and client");e.name="WebAuthnUnavailable",t(e)}},useFido2Credential:function(e,t){HYPRFido2Client.checkWebAuthnSupport(t)&&navigator.credentials.get({publicKey:{challenge:base64ToArrayBuffer(fromBase64URL(e.challenge)),timeout:e.timeout,rpId:e.rpId,userVerification:e.userVerification,allowCredentials:e.allowCredentials}}).then(e=>{let n={id:e.id,rawId:toBase64URL(btoa(bufferToString(e.rawId))),type:e.type,response:{authenticatorData:toBase64URL(btoa(bufferToString(e.response.authenticatorData))),clientDataJSON:toBase64URL(btoa(bufferToString(e.response.clientDataJSON))),signature:toBase64URL(btoa(bufferToString(e.response.signature))),userHandle:toBase64URL(btoa(bufferToString(e.response.userHandle)))}};t(null,n)}).catch(e=>{console.error("Error processing credential assertion request for WebAuthn with code: "+e.code+" and message: "+e.message+" and name: "+e.name),t(e)})},makePublicKey:function(e,t){return e.excludeCredentials&&(e.excludeCredentials=e.excludeCredentials.map(function(e){return e.id=base64ToArrayBuffer(fromBase64URL(e.id)),e.transports=["internal","usb","ble","nfc"],e})),t&&(e.excludeCredentials=[]),{publicKey:{attestation:e.attestation,authenticatorSelection:e.authenticatorSelection,excludeCredentials:e.excludeCredentials,rp:e.rp,user:{id:base64ToArrayBuffer(fromBase64URL(e.user.id)),name:e.user.name,displayName:e.user.displayName},pubKeyCredParams:e.pubKeyCredParams,timeout:e.timeout,challenge:base64ToArrayBuffer(fromBase64URL(e.challenge))}}},isFido2Available(e,t=!0){if(HYPRFido2Client.checkWebAuthnSupport())t?PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable().then(function(t){if(t)e(null,!0);else{const t=new Error("Cannot continue since WebAuthn Platform Authentication is not available on this browser and client");t.name="WebAuthnPlatformUnavailable",e(t,!1)}}):e(null,!0);else{const t=new Error("Cannot continue since WebAuthn is not available on this browser and client");t.name="WebAuthnUnavailable",e(t,!1)}},checkWebAuthnSupport:function(){return void 0===window.PublicKeyCredential||window.PublicKeyCredential,!0}};

Function Overview

Five core functions can be leveraged before and during registration and authentication.


HYPRFido2Client.isFido2Available

Call this function to check FIDO2 browser support. To ensure an optimal user experience, make this check before any of the other functions below.

Parameter Name

Description

Default Value

callback

The callback that gets invoked as a result of this check.

none

requirePlatformAuthenticator

Whether or not to check if a platform authenticator is available at the same time. Default value is true.

true

Example

let isFido2AvailableCallback = (error, result) => {
  if (error !== null) {
    console.log("(isFido2AvailableCallback Callback) There was an error: " + String(error));
    return;
  }
  console.log("(isFido2AvailableCallback Callback) Got use credential result: " + result);
};

HYPRFido2Client.isFido2Available(isFido2AvailableCallback);

HYPRFido2Client.createAttestationOptions

Call this function to get the payload you must send to the FIDO2 server options endpoint for registration.

🚧

Note

Make sure username validation is being handled in your server when making an options request.

The parameters are described below:

Parameter Name

Description

Default Value

username

The username of the user you'd like to register.

none

displayName

The display name of the user you'd like to register.

none

authenticatorAttachment

The authenticator attachment for this registration.

platform

userVerification

The user verification type for this registration.

required

isResidentKeyRequired

Whether or not to use a resident key.

false

attestationType

The attestation type to use for registration.

direct

Example

/**
* @returns {{attestation: *, displayName: *, authenticatorSelection: {authenticatorAttachment: *, userVerification: *, requireResidentKey: *}, username: *}}
*/
createAttestationOptions: function (username,
                                     displayName,
                                     authenticatorAttachment = "platform",
                                     userVerification = "preferred",
                                     isResidentKeyRequired = false,
                                     attestationType = "direct");

HYPRFido2Client.createAssertionOptions

Called to make an options request to your FIDO2 server for authentication.

The parameters are described below:

Parameter Name

Description

Default Value

username

The username for this particular user.

none

userVerification

The user verification type.

preferred

authenticatorAttachment

The authenticator attachment type.

platform

Example

/**
* @returns {{userVerification: *, authenticatorSelection: {authenticatorAttachment: *}, username: *}}
*/
createAssertionOptions: function (username,
                                   userVerification = "preferred",
                                   authenticatorAttachment = "platform");

HYPRFido2Client.createFido2Credential

Call this function when you are registering with FIDO2.

Parameter Name

Description

Default Value

serverAttestationOptionsResponse

This is the options response from the attestation FIDO2 options request.

none

callback

This is your callback function that will be invoked in the event of an error or successful completion.

none

removeExcludeCredentials

Whether or not to remove the exclude credentials list from the server during the create request. *This will allow the user to register the same authenticator on the same computer multiple times

true

Example

createFido2Credential: function (serverAttestationOptionsResponse, callback);

HYPRFido2Client.useFido2Credential

Called when you are authenticating with FIDO2.

Parameter Name

Description

serverAssertionOptionsResponse

This is the JSON response of your assertion options request to the FIDO2 server.

callback

This is your callback function that will be invoked in the event of an error or successful completion.

Example

useFido2Credential: function (serverAssertionOptionsResponse, callback);

User Registration

Use the below steps to register a new user with your application.

Registration Flow DiagramRegistration Flow Diagram

Registration Flow Diagram

  1. Create your options request. Get your registration options by calling the createAttestationOptions function. The example uses the default argument values shown in the Function Overview, excepting the username and display name.
//Pass your arguments to the function 
let attestationOptions = HYPRFido2Client.createAttestationOptions("[email protected]", "John Doe");
  1. Get the registration options from the server. Make a REST API call to your FIDO2 server attestation options request (/attestation/options).

The payload that you pass in the POST request should be the attestationOptions from Step 1.

📘

Developer Tip

HYPR provides a Postman collection with samples of the REST APIs for this step. This collection includes specific payload information you can use. You can see the public APIs that are currently available here.

  1. Create the passwordless credential. Once you get a 200 response from the REST API call in Step 2, call the createFido2Credential function in the SDK to create your local credential.

To call this function, you must define a callback that will be invoked in the event of either an error or completion of the credential creation.

let attestationCallback = (error, result) => {
  if (error !== null) {
    console.log("(Attestation Callback) There was an error: " + String(error));
    return;
  }
  console.log("(Attestation Callback) Got create credential result: " + result);
};

HYPRFido2Client.createFido2Credential(responseFromStep2, attestationCallback);
  1. Complete the registration . Once your callback in Step 3 is called and the credential is created, make a REST API POST request to the FIDO2 server attestation result (/attestation/result) endpoint. The body of the REST API call will be the result in your callback from Step 3.

📘

Developer Tip

HYPR provides a Postman collection with samples of the REST APIs for this step. This collection includes specific payload information that you can use. You can see the public APIs that are currently available here.

User Authentication

Use the steps below to authenticate registered users.

Authentication FlowAuthentication Flow

Authentication Flow

  1. Create your options request. Create the authentication options for the server by calling the createAssertionOptions function on the SDK. The only required parameter here is the username. In the example below, we use the default parameters for user verification and attachment.
let authnOptions = HYPRFido2Client.createAssertionOptions("[email protected]");
  1. Get the authentication options from the server. Once you get your authentication options from Step 1, you must make a REST API POST request to the assertion options (/assertion/options) endpoint on your FIDO2 server.

The payload in this POST request should be the authnOptions from Step 1.

📘

Developer Tip

HYPR provides a Postman collection with samples of the REST APIs for this step. This collection includes specific payload information that you can use. You can see the public APIs that are currently available here.

  1. Use the stored credential. Once you get a successful response from your FIDO2 API in Step 2, you must leverage the SDK to use the previously registered credential.

The useFido2Credential function will take in the response from Step 2 and a callback as parameters. This callback will be invoked by the SDK in either the event of a successful use of the credential, or in the event of an error.

let assertionCallback = (error, result) => {
  if (error !== null) {
    console.log("(Assertion Callback) There was an error: " + String(error));
    return;
  }
  console.log("(Assertion Callback) Got use credential result: " + result);
};

HYPRFido2Client.useFido2Credential(resp, assertionCallback);
  1. Complete the authentication. Once your callback in Step 3 is called and the credential is successfully used, make a REST API POST request to the FIDO2 server assertion result (/assertion/result) endpoint. The body of the REST API call will be the result in your callback from Step 3.

📘

Developer Tip

HYPR provides a Postman collection with samples of the REST APIs for this step. This collection includes specific payload information that you can use. You can see the public APIs that are currently available here.

Error Handling

The below section highlights common errors that can occur when using the SDK, and suggestions on how they should be handled.

❗️

name: WebAuthnUnavailable

Message: Cannot continue since WebAuthn is not available on this browser and client.

Explanation: This error will occur if you try to register or authenticate a user but their browser doesn't support FIDO2 WebAuthn APIs.

If you encounter this error, then you should provide the user with an alternative method for authentication or registration such as a Push to mobile capability.

❗️

name: WebAuthnPlatformUnavailable

Message: Cannot continue since WebAuthn Platform Authentication is not available on this browser and client.

Explanation: If you encounter this error, it means that your authenticator attachment during registration was platform and the user's computer doesn't support platform authenticators in the WebAuthn APIs.

If you encounter this error, give the user an alternative authenticator to register, such as a mobile device or SmartKey device, by leveraging the cross-platform authenticator attachment in your createAttestationOptions request.

❗️

name: InvalidStateError

Message: The user attempted to register an authenticator that contains one of the credentials already registered with the relying party.

Explanation: If you encounter this error, it means that the username provided is already registered on this particular computer with the same authenticator.

If you feel that this is a mistake, you can try deleting the authenticator on the FIDO2 server by using the proper REST API call (see the Postman collection for more details).

If you would like to register the same username multiple times on the same computer, you can do so by removing the excludeCredentials array from the server response in User Registration above.

❗️

name: NotAllowedError

Message: The operation either timed out or was not allowed.

Explanation: If you encounter this error, it can mean one of these items:

  1. The username you're trying to authenticate doesn't have any credentials registered on this computer. This can happen if they never registered or if they removed the credential from their computer or device.

If the user is not registered on this machine, then you should register them first.

  1. The user cancelled the authentication or registration prompt that was given to them by the browser.

  2. The user didn't complete the request within 30 seconds and their authentication or registration request timed out. In this case, you can try authenticating or registering the user again.

❗️

name: NotSupportedError

Message: Either the device has received unexpected request parameters, or the device cannot support this request.

Explanation: If you see this error, it most likely means that you are trying to register a device with the resident key value set to true in the create credentials request.

To overcome the issue, you should set the isResidentKeyRequired parameter to false when creating the FIDO credential.