Documentation Hub
Web SDK
Web SDK
  • Keyless Web SDK Documentation
  • Introduction
    • Components
    • Integration Flows
  • Web SDK Guide
    • Getting Started
    • Enrollment
    • Authentication
    • Browser Requirements
  • Web SDK Reference
    • UI Customization
    • Localization
    • Lockout Policy
    • Error Handling
    • Camera Permission Flow
    • Signing Transactions
Powered by GitBook
On this page
  • Errors Explanation
  • Web Components Error Handling
  • Web Components Errors Explanation

Was this helpful?

  1. Web SDK Reference

Error Handling

The KeylessAuth and KeylessEnroll classes emit 2 kind of error events:

  • The all purpose "error" event

  • The WebSocket specific "ws-error" event

Here's an example of how to handle these errors:

import { KeylessAuth } from '@keyless/sdk-web'

const auth = new KeylessAuth()

auth.on('error', (error) => {
  // handle error
})

auth.on('ws-error', (event, error) => {
  // handle error
  // the event argument is the one emitted by the native WebSocket instance
})

// connecting without a WebSocket URL and username will of course emit an error
auth.connect()

Of course this example also applies to the KeylessEnroll class, each error contains the error code in the message, this is the enum which is also exported by the @keyless/sdk-web package:

enum KeylessError {
  WEB_SOCKET_ERROR = 'WEB_SOCKET_ERROR',
  WEB_SOCKET_OPEN = 'WEB_SOCKET_OPEN',
  WEB_SOCKET_UNEXPECTED_CLOSE = 'WEB_SOCKET_UNEXPECTED_CLOSE',
  WEB_SOCKET_TIMEOUT = 'WEB_SOCKET_TIMEOUT',

  CUSTOMER_UNSET = 'CUSTOMER_UNSET',
  KEY_UNSET = 'KEY_UNSET',
  KEY_ID_UNSET = 'KEY_ID_UNSET',
  USERNAME_UNSET = 'USERNAME_UNSET',
  WEB_SOCKET_URL_UNSET = 'WEB_SOCKET_URL_UNSET',

  IMAGE_KEY_DECODE_FAILED = 'IMAGE_KEY_DECODE_FAILED',
  KEY_DECODE_FAILED = 'KEY_DECODE_FAILED',
  WEB_SOCKET_URL_PARSE_FAILED = 'WEB_SOCKET_URL_PARSE_FAILED',

  NO_FRAMES = 'NO_FRAMES',
  USER_LOCKED_OUT = 'USER_LOCKED_OUT',

  FRAME_DECODE_FAILED = 'FRAME_DECODE_FAILED',
  FRAME_DRAW_FAILED = 'FRAME_DRAW_FAILED',
  FRAME_ENCRYPT_FAILED = 'FRAME_ENCRYPT_FAILED',
  FRAME_KEY_ENCRYPT_FAILED = 'FRAME_KEY_ENCRYPT_FAILED',
  FRAME_NO_DATA = 'FRAME_NO_DATA',

  SERVER_FACE_DOES_NOT_MATCH = 'SERVER_FACE_DOES_NOT_MATCH',
  SERVER_FORBIDDEN = 'SERVER_FORBIDDEN',
  SERVER_IMAGE_ENCRYPT_FAILED = 'SERVER_IMAGE_ENCRYPT_FAILED',
  SERVER_INTERNAL_ERROR = 'SERVER_INTERNAL_ERROR',
  SERVER_NO_ATTEMPTS_LEFT = 'SERVER_NO_ATTEMPTS_LEFT',
  SERVER_RECOGNITION_FAILED = 'SERVER_RECOGNITION_FAILED',
  SERVER_TIMEOUT = 'SERVER_TIMEOUT',
  SERVER_UNAVAILABLE_SERVICE = 'SERVER_UNAVAILABLE_SERVICE',
  SERVER_UNPROCESSABLE_EVENT = 'SERVER_UNPROCESSABLE_EVENT',
  SERVER_USER_ALREADY_ENROLLED = 'SERVER_USER_ALREADY_ENROLLED',
  SERVER_USER_NOT_FOUND = 'SERVER_USER_NOT_FOUND',
  SERVER_USER_LOCKED_OUT = 'SERVER_USER_LOCKED_OUT'
}

Errors Explanation

Error

Triggers

WEB_SOCKET_ERROR

Forwarded from the native WebSocket instance “error” event.

WEB_SOCKET_OPEN

Triggered by creating a new native WebSocket instance, could also be caused by a timeout during the connection to the WebSocket.

WEB_SOCKET_UNEXPECTED_CLOSE

Triggered after the “ws-close” event, it is triggered when the WebSocket closes in a state where it is not supposed to be closing.

  • BeginStream

  • FrameResults

  • StopStream

This is the list of events which are considered as unexpected if the WebSocket closes.

WEB_SOCKET_TIMEOUT

Triggered after the WebSocket connection is open for the specified amount of time, by default this timeout is 1 minute.

CUSTOMER_UNSET

Triggered when the customer.name has not been provided to the connect options.

KEY_UNSET

Triggered when the key.value has not been provided to the connect options.

KEY_ID_UNSET

Triggered when the key.id has not been provided to the connect options.

USERNAME_UNSET

Triggered when the username has not been provided to the connect options.

WEB_SOCKET_URL_UNSET

Triggered when the ws.url has not been provided to the connect options.

IMAGE_KEY_DECODE_FAILED

Triggered when an invalid base64 value is provided to the image.key option.

KEY_DECODE_FAILED

Triggered when an invalid base64 value is provided to the key.value option.

WEB_SOCKET_URL_PARSE_FAILED

Triggered when an invalid URL is provided to the ws.url option.

NO_FRAMES

Triggered when there are no frames to send to the WebSocket, potential causes:

  • The collectFrame method was not called or used correctly by the integrator of @keyless/sdk-web

  • There was an issue with the MediaStream and the @keyless/sdk-web-components library was unable to capture any frame

USER_LOCKED_OUT

Triggered when the lockout policy is enabled and the user has failed the specified amount of times in a row the authentication or enrollment.

The user will be locked out for the specified amount of time, which by default is 5 minutes.

The user will be locked out after the specified amount of times in a row, which by default is 5 attempts.

FRAME_DECODE_FAILED

Triggered when an invalid base64 value is passed to the collectFrame method.

FRAME_DRAW_FAILED

Triggered when it is impossibile to draw the MediaStream frame, this could happen for various reasons:

  • The user did not grant camera permissions, so there is no stream to draw from.

  • The browser does not support Canvas or ImageCapture APIs, should be unlikely.

  • The MediaStream is absent or undefined for unknown reasons.

FRAME_ENCRYPT_FAILED

Triggered when encryption of the frame fails, technically it should never happen.

FRAME_KEY_ENCRYPT_FAILED

Triggered when encryption of the encryption key of the frames fails, meaning that a bad public key was provided to the key.value option.

FRAME_NO_DATA

Triggered when the collectFrame method is used improperly by the integrator, meaning that neither a base64 encoded image nor a video element or MediaStream were passed to the function.

SERVER_FACE_DOES_NOT_MATCH

Triggered when the face does not match with the one that was enrolled.

SERVER_FORBIDDEN

Triggered when an invalid authorization.token was provided.

SERVER_IMAGE_ENCRYPT_FAILED

Triggered when the server was unable to decrypt the frame sent by the client.

SERVER_INTERNAL_ERROR

Triggered by any non-classified error on the server, a reason is always paired with this error which gives further details on the error, useful for debugging.

SERVER_NO_ATTEMPTS_LEFT

Triggered when all circuits have been burned by the user, meaning that the user has to re-enroll to be able to authenticate again.

SERVER_RECOGNITION_FAILED

Triggered when the user failed the biometric pipeline.

SERVER_TIMEOUT

Triggered when the server times out, either due to an internal long running operation that timed out or due to the client taking too much time to exchange messages.

SERVER_UNAVAILABLE_SERVICE

Triggered when a service that Authentication Service is dependant on is not available, meaning that the system is not fully operational.

SERVER_UNPROCESSABLE_EVENT

Triggered when the WebSocket route protocol is misused, technically should never happen.

SERVER_USER_ALREADY_ENROLLED

Triggered when the user is trying to enroll but they are already enrolled with that username.

SERVER_USER_NOT_FOUND

Triggered when the user is trying to authenticate with a username that has not been enrolled first.

SERVER_USER_LOCKED_OUT

Triggered when the user has been locked out on the server. This lockout is enabled by default and lasts 10 minutes, the user needs to fail authentication or enrollment 5 times in a row in a minute.

Web Components Error Handling

Handling errors in the web components is very similar to how they are handled in the @keyless/sdk-web library, so check out that part first because those errors are inherited by the web components: Errors Explanation

Of course the web components naturally have more complexity, let’s go in order with some examples on how to handle all the errors emitted by the web components.

Here's an example of handling the "error" event:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Auth</title>
    <style>
      * {
        box-sizing: border-box;
      }

      body {
        align-items: center;
        display: flex;
        justify-content: center;
        margin: 0;
        min-height: 100vh;
        padding: 8px;
      }

      kl-auth {
        border: 1px solid lightgray;
      }
    </style>
  </head>
  <body>
    <kl-auth
      customer="CUSTOMER_NAME"
      enable-camera-instructions
      key="IMAGE_ENCRYPTION_PUBLIC_KEY"
      key-id="IMAGE_ENCRYPTION_KEY_ID"
      lang="en"
      size="375"
      theme="light"
      username="USERNAME"
      ws-url="KEYLESS_AUTHENTICATION_SERVICE_URL"
    ></kl-auth>
    <script src="./node_modules/@keyless/sdk-web-components/elements/auth/auth-element.iife.js"></script>
    <script>
      const auth = document.querySelector('kl-auth')

      auth.addEventListener('error', (event) => {
        // will print the error code
        console.error(event.message)
      })
    </script>
  </body>
</html>

We extend the native ErrorEvent browser implementation here, so you can find the error code quite easily inside the event message.

The error code can be anything from the @keyless/sdk-web KeylessError enum, with on top the errors of the web components, here’s their enums:

enum KeylessComponentsError {
  CAMERA_CHECK_FAILED = 'CAMERA_CHECK_FAILED',

  CAMERA_NO_MEDIA_DEVICES = 'NO_MEDIA_DEVICES',
  CAMERA_NO_MEDIA_STREAM = 'NO_MEDIA_STREAM'
}

Web Components Errors Explanation

Error

Triggers

CAMERA_CHECK_FAILED

Triggered when camera checks are enabled and the user failed to meet the requested conditions.

CAMERA_NO_MEDIA_DEVICES

Triggered when there are no media devices capable of video output, this means that the user either does not have a camera or they did not grant the camera permissions.

CAMERA_NO_MEDIA_STREAM

Triggered when there is no media stream available, explanation is the same as NO_MEDIA_DEVICES error.

The "ws-error" event is emitted when the WebSocket native instance emits an error, here's an example:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Auth</title>
    <style>
      * {
        box-sizing: border-box;
      }

      body {
        align-items: center;
        display: flex;
        justify-content: center;
        margin: 0;
        min-height: 100vh;
        padding: 8px;
      }

      kl-auth {
        border: 1px solid lightgray;
      }
    </style>
  </head>
  <body>
    <kl-auth
      customer="CUSTOMER_NAME"
      enable-camera-instructions
      key="IMAGE_ENCRYPTION_PUBLIC_KEY"
      key-id="IMAGE_ENCRYPTION_KEY_ID"
      lang="en"
      size="375"
      theme="light"
      username="USERNAME"
      ws-url="KEYLESS_AUTHENTICATION_SERVICE_URL"
    ></kl-auth>
    <script src="./node_modules/@keyless/sdk-web-components/elements/auth/auth-element.iife.js"></script>
    <script>
      const auth = document.querySelector('kl-auth')

      auth.addEventListener('ws-error', (event) => {
        // will print the native WebSocket error event
        console.error(event.detail.event)
        
        // will print the error code
        console.error(event.detail.error.message)
      })
    </script>
  </body>
</html>

We use a custom error here called WebSocketErrorEvent which contains both the native WebSocket event and the error generated by us with a predictable error code.

Last updated 3 months ago

Was this helpful?