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
  • Headless Integration
  • Headless Web Integration
  • Web Component Integration

Was this helpful?

  1. Web SDK Guide

Authentication

Last updated 1 month ago

Was this helpful?

Authentication is the biometric equivalent of "signing-in". During authentication Keyless compares the user's facial biometrics with the ones computed during .

If the biometrics match, Keyless authenticates the user.

Headless Integration

The @keyless/sdk-web library lets you integrate the Keyless Web SDK however you want in terms of UI/UX, let's see a basic example of authentication:

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

const auth = new KeylessAuth()

// in order to perform an authentication you need to pass a liveness check,
// this means that you need to have multiple natural different frames of the face,
// they should be captured from a live camera feed like a webcam
const frames = ['base16-frame-1', 'base16-frame-2', '...']

auth.on('begin-stream', async () => {
  await auth.collectFrame(frames[0])
  await auth.sendFrame()
   
  // remove used frame
  frames.shift()
})

auth.on('error', (event) => {
  // will log the error code
  console.error(event.message)
})

auth.on('frame-results', () => {
  if (frames.length <= 0) {
    throw new Error('No more frames')
  }
  
  // some time needs to pass between one frame and the other,
  // this is handled gracefully in our web components by having a framerate of 4fps
  setTimeout(async () => {
    await auth.collectFrame(frames[0])
    await auth.sendFrame()
    
    // remove used frame
    frames.shift()
  }, 200)
})

auth.on('finished', (event) => {
  // will log details about this authentication
  console.log(event.data)
})

await auth.connect({
  customer: { name: 'CUSTOMER_NAME' },
  key: { id: 'IMAGE_ENCRYPTION_KEY_ID', value: 'IMAGE_ENCRYPTION_PUBLIC_KEY' },
  username: 'USERNAME',
  ws: { url: 'KEYLESS_AUTHENTICATION_SERVICE_URL' }
})

In this example we handle all the necessary events to perform an authentication with a continous stream of face frames, and if it fails the error code will be logged to the console.

Headless Web Integration

In the previous section we showed how to integrate @keyless/sdk-web in the simplest way without taking into account how to capture the frames from a webcam. Below we now expose a few utilities from the library that will simplify the integration, let's see them in action:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Auth</title>
  </head>
  <body>
    <video autoplay></video>
    <script src="./node_modules/@keyless/sdk-web/index.iife.js"></script>
    <script></script>
    <script>
      let auth, video, stream, collectFrameIntervalID

      const { 
        DEFAULT_KEYLESS_MEDIA_TRACK_FRAME_RATE,
        getVideoMediaStream,
        KeylessAuth
      } = window.Keyless

      auth = new KeylessAuth()
      video = document.querySelector('video')

      auth.on('begin-stream', async () => {
        // will wait for at least a frame to be available
        await auth.waitForFrames()

        // will send a frame
        await auth.sendFrame()
      })

      auth.on('error', async (error) => {
        // will log the error code
        console.error(error.message)

        // will pause the video, stop the stream and clear the collect frame interval
        video.pause()
      })

      auth.on('frame-results', async (event) => {
        // will log the frame results
        console.log(event.data)

        // will wait for at least a frame to be available
        await auth.waitForFrames()

        // will send a frame
        await auth.sendFrame()
      })

      auth.on('finished', async (event) => {
        // will log details about this authentication
        console.log(event.data)

        // will pause the video, stop the stream and clear the collect frame interval
        video.pause()
      })

      video.addEventListener('play', async () => {
        // in case play fires multiple times in a row, we clear the interval
        clearInterval(collectFrameIntervalID)

        collectFrameIntervalID = setInterval(async () => {
          // will collect a frame from the video or stream and store it in memory,
          // this ensures a constant capture rate not affected by connection speed
          await auth.collectFrame(video, stream)
        }, 1000 / DEFAULT_KEYLESS_MEDIA_TRACK_FRAME_RATE)

        auth.connect({
          customer: { name: 'CUSTOMER_NAME' },
          key: { id: 'IMAGE_ENCRYPTION_KEY_ID', value: 'IMAGE_ENCRYPTION_PUBLIC_KEY' },
          username: 'USERNAME',
          ws: { url: 'KEYLESS_AUTHENTICATION_SERVICE_URL' }
        })
      })

      video.addEventListener('pause', async () => {
        for (let track of stream.getTracks()) {
          try {
            track.stop()
          } catch (e) {}
        }

        clearInterval(collectFrameIntervalID)
      })
    </script>
    <script>
      getVideoMediaStream().then((stream) => {
        if (stream instanceof Error) {
          // will log the error message
          return console.error(stream.message)
        }

        video.srcObject = stream
      })
    </script>
  </body>
</html>

This snippet will start a video media stream which will then be played through the video element. Once the video starts playing an interval is set which collects the frames from the video or stream based on browser compatibility with our capture algorithms.

These frames are encrypted and sent to the server when requested in the begin-stream and frame-results events, the flow then goes on as normal with authentication either succeeding or failing.

Web Component Integration

Previously we explained how to perform authentication in a headless way with the @keyless/sdk-web package, now we'll provide an example of doing so with raw HTML syntax.

<!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 log the error code
        console.log(event.message)
      })

      auth.addEventListener('finished', (event) => {
        // will log details about this authentication
        console.log(event.detail)
      })
    </script>
  </body>
</html>

That's it, everything is handled by the @keyless/sdk-web-components package, especially the more complex parts of capturing camera frames and sending them at a proper framerate to the Authentication Service.

enrollment