Authentication

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

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:

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

const auth = new KeylessAuth()

// implies that the video element is already present in the DOM
const 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()
})

let collectFrameIntervalID, stream

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)
})

getVideoMediaStream().then((value) => {
  if (value instanceof Error) {
    // will log the error message
    return console.error(value.message)
  }

  stream = value
  video.srcObject = value
})

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.

import '@keyless/sdk-web-components/elements/auth/auth-element'
import { useEffect, useRef } from 'react'

export function KeylessAuth() {
  const ref = useRef(null)

  onError = (event) => {
    // will log the error code
    console.log(event.message)
  }

  onFinished = (event) => {
    // will log details about this authentication
    console.log(event.detail)
  }

  useEffect(() => {
    ref.current?.addEventListener('error', onError)
    ref.current?.addEventListener('finished', onFinished)

    return () => {
      ref.current?.removeEventListener('error', onError)
      ref.current?.removeEventListener('finished', onFinished)
    }
  }, [])

  return (
    <kl-auth
      customer='CUSTOMER_NAME'
      enable-camera-instructions
      key='IMAGE_ENCRYPTION_PUBLIC_KEY'
      key-id='IMAGE_ENCRYPTION_KEY_ID'
      lang='en'
      ref={ref}
      size='375'
      theme='light'
      username='USERNAME'
      ws-url='KEYLESS_AUTHENTICATION_SERVICE_URL'
    />
  )
}

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.

Last updated

Was this helpful?