Enrollment is the process of registering a new user by connecting their facial biometrics to a Keyless account. During this process, a full and unobstructed view of the user's face is required.
Enrollment with Web SDK can happen in two ways:
Live Enrollment, through the Keyless Web SDK JS libraries described below.
, through the Keyless Authentication Service
On this page we'll explain how to perform only interactive live enrollment on the front-end.
Note Keyless also supports , so that users could also be enrolled from IDV Bridge OnPremise or the Mobile SDK and still be authenticated via the Web SDK JS at a later date.
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 enrollment:
import { KeylessEnroll } from '@keyless/sdk-web'
const enroll = new KeylessEnroll()
// in order to perform an interactive enrollment 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', '...']
enroll.on('begin-stream', async () => {
// will store the frame in memory
await enroll.collectFrame(frames[0])
// will send a frame
await enroll.sendFrame()
// remove used frame
frames.shift()
})
enroll.on('error', (error) => {
// will log the error code
console.error(error.message)
})
enroll.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 enroll.collectFrame(frames[0])
await enroll.sendFrame()
// remove used frame
frames.shift()
}, 200)
})
enroll.on('finished', (event) => {
// will log details about this enrollment
console.log(event.data)
})
await enroll.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 enrollment with a continous stream of face frames, and if it fails the error code will be logged to the console.
Headless Web Integration
The previous section explained how to integrate @keyless/sdk-web in the simplest way without taking into account how to capture the frames from a webcam. We can also 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>Enroll</title>
</head>
<body>
<video autoplay></video>
<script src="./node_modules/@keyless/sdk-web/index.iife.js"></script>
<script></script>
<script>
let enroll, video, stream, collectFrameIntervalID
const {
DEFAULT_KEYLESS_MEDIA_TRACK_FRAME_RATE,
getVideoMediaStream,
KeylessEnroll
} = window.Keyless
enroll = new KeylessEnroll()
video = document.querySelector('video')
enroll.on('begin-stream', async () => {
// will wait for at least a frame to be available
await enroll.waitForFrames()
// will send a frame
await enroll.sendFrame()
})
enroll.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()
})
enroll.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 enroll.waitForFrames()
// will send a frame
await enroll.sendFrame()
})
enroll.on('finished', async (event) => {
// will log details about this enrollment
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 enroll.collectFrame(video, stream)
}, 1000 / DEFAULT_KEYLESS_MEDIA_TRACK_FRAME_RATE)
enroll.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 enrollment, either succeeding or failing.
Web Component Integration
Now that we have explained how to perform enrollment in a headless way with the @keyless/sdk-web package, here is an example of doing so with raw HTML syntax.
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.