Test user registration and deregistration with the FIDO2 Sample Relying Party Web App

You can use the FIDO2 Sample Relying Party Web AppClosed Stand-alone component that allows you to test and simulate the end-to-end capabilities of the FIDO2 registration and authentication flows. With this app, you can also deregister all the user keys from the FIDO2 Server. to test the user registration and deregistration flows.

Registration flow code samples

The code samples in this article do NOT contain actual production code, rather, the examples used here serve to demonstrate how to integrate FIDO2 into your website.

Initialization

To initialize the registration process, the user must enter their user information in the REGISTER tab of the FIDO2 Sample Relying Party Web App, select the respective authenticator Attachment option, and click SEND.

When registration is triggered, theFIDO2 Sample Relying Party Web App sends an initialization request to the OneSpan Trusted Identity platform API via the following endpoint:

The exact structure of the request body can be verified on the Platform API Sandbox page. The initializationResponse should look like this:

{
  "requestID": registration:9a97ad39-3581-4c20-99f5-dacd41bcffe4,
  "registrationRequest": "{\"rp\":{\"id\":\"sampletest-tenant.clockwork-dev.tid.onespan.cloud\",\"name\":\"OneSpan Corp\",\"icon\":\"https://www.onespan.com/themes/custom/onespan/images/logo.svg\"},\"user\":{\"name\":\"test1@sampletest-tenant\",\"icon\":\"https://www.onespan.com/themes/custom/onespan/images/logo.svg\",\"id\":\"124gx9TOLk_B6tbTlkZN1CHlUOE6UAdYZD63QgxsID2sa-YIN8GhagEfRQgd96H48xEiKBiHln6SNRvBME_jWQ\",\"displayName\":\"test1\"},\"challenge\":\"hXYd7jWooAWFRpYPJHouW_2hklZ2kxuC7JdsatPzEvxJi4A8Ye7JXyZzca4JC4v5uj4MEL1_tpmfK3BEbGE3Tw\",\"pubKeyCredParams\":[{\"type\":\"public-key\",\"alg\":-257},{\"type\":\"public-key\",\"alg\":-258},{\"type\":\"public-key\",\"alg\":-259},{\"type\":\"public-key\",\"alg\":-37},{\"type\":\"public-key\",\"alg\":-38},{\"type\":\"public-key\",\"alg\":-39},{\"type\":\"public-key\",\"alg\":-7},{\"type\":\"public-key\",\"alg\":-35},{\"type\":\"public-key\",\"alg\":-36},{\"type\":\"public-key\",\"alg\":-8},{\"type\":\"public-key\",\"alg\":-43}],\"timeout\":100000,\"authenticatorSelection\":{\"authenticatorAttachment\":\"platform\",\"requireResidentKey\":false,\"userVerification\":\"required\"},\"attestation\":\"none\",\"extensions\":{\"authnSel\":[\"fa2a81f4-8412-41f9-8656-c94487f224ec\"],\"exts\":true,\"biometricPerfBounds\":{\"FAR\":0.02,\"FRR\":0.02},\"location\":false,\"uvi\":false,\"uvm\":false},\"status\":\"ok\",\"errorMessage\":\"\"}"
}

Communication with the client platform

In this step, you need to call the WebAuthn API from the client-side JavaScript of your website and prompt the user to create a new set of credentials generated with the authenticator.

navigator.credentials.create(credentialCreationOptions)

The credentialCreationOptions object should be based on the initializationResponse received during the initialization step.

var resp = JSON.parse(initializationResponse.registrationRequest);

var credentialCreationOptions = {
  publicKey: {
    rp: resp.rp,
    challenge: bufferDecode(resp.challenge),
    user: {
      id: bufferDecode(resp.user.id),
      name: resp.user.name,
      displayName: resp.user.displayName
    },
    pubKeyCredParams: resp.pubKeyCredParams,
    timeout: resp.timeout,
    attestation: resp.attestation,
    authenticatorSelection: resp.authenticatorSelection,
    excludeCredentials: resp.excludeCredentials === undefined ? []
     : resp.excludeCredentials.map(item => Object.assign({}, item, {
        id: bufferDecode(item.id)
      })),
    extensions: {}
  }
};

A custom bufferDecode function is defined in the following way:

function bufferDecode(value) {
  const s = base64DecodeUrl(value);
  const s1 = atob(s);
  return Uint8Array.from(s1, c => c.charCodeAt(0));
}

function base64DecodeUrl(str) {
  str = str + Array((4 - str.length % 4) % 4 + 1).join('=');
  return str.replace(/-/g, '+').replace(/_/g, '/');
}

When navigator.credentials.create() is called, the browser prepares a list of available authenticators.

At this point, the user needs to select an authenticator to trigger the credential creation. Once selected, the user is prompted to provide their consent, and a private-public key pair is created. The public key is received via a promise that contains the PublicKeyCredential object.

navigator.credentials.create(credentialCreationOptions)
  then(publicKeyCredential => {
    finalize(publicKeyCredential);
})
  catch(e => {    // error handling
});

Finalization

In the finalization step, you need to send a request to the finalize endpoint of the OneSpan Trusted Identity platform APIClosed Provides the endpoints that are required for the successful completion of the operations.. The body is prepared based on the previously received PublicKeyCredential object. The following POST request is sent to the OneSpan Trusted Identity platform API:

with the following body:

const body = {
  registrationResponse: JSON.stringify({
    id: publicKeyCredential.id,
    rawId: toBase64Url(publicKeyCredential.rawId),
    type: "public-key",
    response: {
      "attestationObject": toBase64Ur(publicKeyCredential.response.attestationObject),
      "clientDataJSON": toBase64Url(publicKeyCredential.response.clientDataJSON)
    }
  }),
  fidoProtocol: "FIDO2",
  requestID: "registration:9a97ad39-3581-4c20-99f5-dacd41bcffe4"
};

function toBase64Url(arrayBuffer) {
  let binary = '';  const bytes = new Uint8Array(arrayBuffer);
  const len = arrayBuffer.byteLength;
  for (let i = 0; i < len; i++) {
  binary += String.fromCharCode(bytes[i]);
}
  return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
}

The value of the requestID in the body should match the value of the requestID that was retrieved from the initializationResponse.

For more information on the structure, refer to the World Wide Web Consortium (W3C) Web Authentication documentation.

Deregister the authenticator

In the DEREGISTER tab of the FIDO2 Sample Relying Party Web App, you can deregister user keys on the FIDO2 Server side by calling the following endpoint in the OneSpan Trusted Identity platform API:

FIDO2 does not have a deregistration ceremony that allows a request from the Relying Party to the FIDO authenticator to delete authentication keys that are bound to a user account. For the FIDO2 Sample Relying Party Web App, the DEREGISTER tab allows you to delete the public keys of a user that are stored on the FIDO2 Server. Note that this action will also delete the user!