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?