Authentication
Prerequisites
Headless Integration
import {
addKeylessEventListeners,
createKeylessAuth,
createKeylessMediaStream,
getKeylessCameraPermissionState,
getKeylessVideoMediaDevices,
getLastKeylessFrameTriggeredBiometricFilters,
importKeylessWebAssemblyModuleOrThrow,
isKeylessVideoMediaStreamAvailable,
KeylessError,
openKeylessWebSocketConnection,
reduceKeylessBiometricFiltersToTriggered,
removeKeylessEventListeners
} from '@keyless/sdk-web'
function requestTransactionJwtVerification(jwt) {}
function requestUserCameraPermission() {}
function handleCameraOperativityError(error) {}
function handleImportKeylessWebAssemblyModuleError(error) {}
function handleCreateKeylessMediaStreamError(error) {}
function handleOpenKeylessWebSocketConnectionError(error) {}
/**
* This event is fired when an error occurs during the authentication process.
* The error object contains a `code` property that indicates the type of error.
*/
function onKeylessError(sym, error) {
/**
* Removing event listeners is advised on terminal events since
* no more than one attempt is allowed per authentication symbol.
*/
removeKeylessEventListeners(sym)
// will log the error code
console.error(error.message)
}
/**
* This event is fired when the authentication process is complete.
* It does not fire for failed attempts, only successful ones.
*/
function onKeylessFinished(sym, message) {
/**
* Removing event listeners is advised on terminal events since
* no more than one attempt is allowed per authentication symbol.
*/
removeKeylessEventListeners(sym)
/**
* The `transactionJwt` is a JSON Web Token (JWT) that contains information
* about the authentication transaction.
*
* This token is signed by the Keyless Authentication Service and can be used
* to verify the authenticity of the transaction.
*
* This operation is strictly backend-to-backend and should never be performed
* in client-side code.
*/
requestTransactionJwtVerification(message.transactionJwt)
}
/**
* This event is useful for providing real-time feedback to users during
* the authentication process, such as prompting them to adjust their position
* or lighting conditions to improve biometric recognition.
*/
function onKeylessFrameResults(sym, message) {
let filters
/**
* Returns an array of biometric filters that were triggered in the last frame.
* If no biometric filters were triggered, an empty array is returned.
*/
filters = reduceKeylessBiometricFiltersToTriggered(message.filters)
/**
* Optionally, this function can be used to retrieve the filters that were triggered
* in the last frame.
*
* This can be useful if you need to access the last frame's triggered filters outside
* of the frame results event.
*
* If this function is used then this event is useful for requesting an update to the UI.
*/
filters = getLastKeylessFrameTriggeredBiometricFilters(sym)
}
async function ensureCameraOperativity() {
let devices, state
devices = await getKeylessVideoMediaDevices()
/**
* If the error is MEDIA_DEVICES_NO_VIDEO_INPUTS, it means that
* the user does not have any camera available.
*/
if (devices instanceof Error && devices.message === KeylessError.MEDIA_DEVICES_NO_VIDEO_INPUTS) throw devices
state = await getKeylessCameraPermissionState()
/**
* If the camera permission state is not 'granted', request
* the user to grant camera access.
*/
if (state !== 'granted') {
/**
* Ideally this function should take the user to a UI prompt
* where they can grant camera access to the website.
*
* The easiest way to trigger the browser's camera permission prompt
* is to call isKeylessVideoMediaStreamAvailable(), which will return
* a boolean indicating whether the user granted camera access or not.
*/
requestUserCameraPermission()
throw new Error('camera permission state is not granted')
}
devices = await getKeylessVideoMediaDevices()
/**
* If the error is MEDIA_DEVICES_EMPTY_VIDEO_INPUT_LABEL, it means that
* even though the user has granted camera access, the browser requires
* the user to start a video stream to be able to read the camera labels.
*
* In this case, we perform a throwaway getUserMedia() request with
* isKeylessVideoMediaStreamAvailable() to start a video stream
* to be able to read the camera labels.
*/
if (devices instanceof Error && devices.message === KeylessError.MEDIA_DEVICES_EMPTY_VIDEO_INPUT_LABEL) {
let available
available = await isKeylessVideoMediaStreamAvailable()
if (!available) throw new Error('video media stream is not available')
devices = await getKeylessVideoMediaDevices()
}
/**
* If we still have an error, throw an error to indicate that
* the media devices still could not be read correctly.
*/
if (devices instanceof Error) throw devices
}
async function authenticateWithKeyless() {
let imprt, auth, options, stream, open
/**
* Create a Keyless authentication symbol.
*
* This symbol must be kept in memory for the duration of the authentication process.
* To perform multiple authentications, a new symbol must be created for each authentication.
*/
auth = createKeylessAuth()
/**
* Add event listeners through the Keyless authentication symbol.
* These listeners will handle events during the authentication process.
*/
addKeylessEventListeners(auth, [
{ name: 'error', callback: (error) => onKeylessError(auth, error) },
{ name: 'finished', callback: (message) => onKeylessFinished(auth, message) },
{ name: 'frame-results', callback: (message) => onKeylessFrameResults(auth, message) }
])
options = {
customer: { name: 'CUSTOMER_NAME' },
key: { id: 'IMAGE_ENCRYPTION_KEY_ID', value: 'IMAGE_ENCRYPTION_PUBLIC_KEY' },
transaction: {
data: 'DATA_FROM_CUSTOMER_SERVER_TO_BE_SIGNED'
},
username: 'USERNAME',
ws: { url: 'KEYLESS_AUTHENTICATION_SERVICE_URL' }
}
/**
* Create a media stream from the user's video input media device.
* This stream will be used to capture video frames for biometric analysis.
*
* Note: The user must grant permission to access the media device.
*/
stream = await createKeylessMediaStream()
if (stream instanceof Error) return handleCreateKeylessMediaStreamError(stream)
/**
* Open a WebSocket connection to the Keyless Authentication Service.
* This connection will be used to process video frames and receive authentication results.
*/
open = await openKeylessWebSocketConnection(auth, options)
if (open instanceof Error) return handleOpenKeylessWebSocketConnectionError(open)
}
importKeylessWebAssemblyModuleOrThrow()
.then(() =>
ensureCameraOperativity()
.then(() => authenticateWithKeyless())
.catch(handleCameraOperativityError)
)
.catch(handleImportKeylessWebAssemblyModuleError)
Web Component Integration
Last updated
Was this helpful?