--- title: "Test User Registration with the FIDO2 Bank Demo Web App" slug: "oca-ig-test-user-registration-with-the-fido2-bank-demo-web-app" updated: 2025-07-04T10:09:40Z published: 2025-07-08T14:14:51Z canonical: "docs.onespan.com/oca-ig-test-user-registration-with-the-fido2-bank-demo-web-app" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.onespan.com/llms.txt > Use this file to discover all available pages before exploring further. # Test User Registration with the FIDO2 Bank Demo Web App You can use the FIDO2 Bank Demo Web App to test the user registration flow. ## Registration flow code samples > The code samples in this article do NOT contain actual production code, rather, the examples used here serve to demonstrate the registration flow for FIDO2. ### Initialization To initialize the registration process, the user must enter their user name in the FIDO2 Bank Demo Web App, select the respective Authenticator attachment option, and click Register. When the registration is triggered, the FIDO2 Bank Demo Web App sends an initialization request to the OneSpan Trusted Identity platform API via the following endpoint: - [POST /users/{userID@domain}/generate-fido-registration-request](https://community.onespan.com/products/onespan-cloud-authentication/sandbox#/FIDO Registrations/generateFidoRegistrationRequest) The exact structure of the request body can be verified on the [Platform API Sandbox](https://community.onespan.com/products/onespan-cloud-authentication/sandbox) page. The initializationResponse should look like this: ```plaintext {     "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, the WebAuthn API is called from the client-side JavaScript of your website and prompts the user to create a new set of credentials generated with the authenticator. ```plaintext navigator.credentials.create(credentialCreationOptions) ``` The credentialCreationOptions object should be based on the initializationResponse received during the initialization step. ```plaintext 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: ```plaintext 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. ```plaintext navigator.credentials.create(credentialCreationOptions)   then(publicKeyCredential => {     finalize(publicKeyCredential); })   catch(e => {    // error handling }); ``` ### Finalization In the finalization step, a POST request is sent to the OneSpan Trusted Identity platform API with the following endpoint: - [POST /users/{userID@domain}/register-fido-device](https://community.onespan.com/products/onespan-cloud-authentication/sandbox#/FIDO Registrations/registerFidoDeviceUserUsingPOST) The body is prepared based on the previously received PublicKeyCredential object. This request contains the following body: ```plaintext 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](https://www.w3.org/TR/2019/REC-webauthn-1-20190304/).