Amplify UI

Face Liveness

Amplify UI FaceLivenessDetector provides a UI component for Amazon Rekognition Face Liveness that helps developers verify that only real users, not bad actors using spoofs, can access your services.

Amplify UI FaceLivenessDetector is powered by Amazon Rekognition Face Liveness. The following screenshots shows an example of FaceLivenessDetector in action.

Screen shots of Liveness component on Web

To learn more about spoof attempts deterred by Face Liveness, please see this demonstration video on YouTube.

Quick start

Prerequisites:

  1. Install and configure the Amplify CLI by following this guide.
  2. A backend that is setup following the Amazon Rekognition Face Liveness developer guide.

Step 1. Configure Auth

There are three methods to setup the Amazon Cognito resources needed for Amplify Auth. The most common is the Amplify CLI create flow which asks a series of questions and will configure both a User Pool and Identity Pool automatically. The second option is the Amplify CLI import flow which adds an existing Cognito resource into Amplify. Finally the third is to reuse or create a Cognito Identity Pool manually and to add it into your application.

Note: Using Cognito does not mean that you have to migrate your users. By default, FaceLivenessDetector uses a Cognito Identity Pool, for the sole purpose of signing requests to Rekognition.

Use the Amplify CLI to automatically configure and manage your Cognito Identity and User Pool for you.

FaceLivenessDetector uses Amplify Auth by default to authorize users to perform the Face Liveness check. If you are using Amplify for the first time, follow the instructions for installing the Amplify CLI.

Set up a new Amplify project

$ amplify init
? Enter a name for the project reactliveness
? Enter a name for the environment dev
? Choose your default editor: Visual Studio Code
? Choose the type of app that you're building javascript
Please tell us about your project
? What javascript framework are you using react
? Source Directory Path:  src
? Distribution Directory Path: build
? Build Command:  npm run-script build
? Start Command: npm run-script start

Add the auth category

$ amplify add auth
 Do you want to use the default authentication and security configuration? Manual configuration
 
 Select the authentication/authorization services that you want to use: User Sign-Up, Sign-In, connected with AWS IAM controls (Enables per-user Storage features for images or other content, Analytics, and more)
 
 Provide a friendly name for your resource that will be used to label this category in the project: <default>
 
 Enter a name for your identity pool. <default>
 
 Allow unauthenticated logins? (Provides scoped down permissions that you can control via AWS IAM) Yes
 
 <Choose defaults for the rest of the questions>   

Push to create the resources

$ amplify push
✔ Successfully pulled backend environment dev from the cloud.

Current Environment: dev

| Category | Resource name    | Operation | Provider plugin   |
| -------- | ---------------- | --------- | ----------------- |
| Auth     | reactlive••••••• | Create    | awscloudformation | 

If you have an existing Amplify backend, run amplify pull to sync your aws-exports.js with your cloud backend.

Once complete you should now have an aws-exports.js file in your src directory with your latest Amplify backend configuration.

If you previously had unmanaged resources that you want to manage with Amplify you can use the CLI to import your Cognito resources.

FaceLivenessDetector uses Amplify Auth by default to authorize users to perform the Face Liveness check. Follow the instructions for Amplify CLI (Import) to manage your Cognito resources with Amplify.

Once complete you should now have an aws-exports.js file in your src directory with your latest Amplify backend configuration.

Use this option if you already have a Cognito identity/user pools that you do not want to import to Amplify, or want to manage Cognito resources yourself or with a 3rd party resource management tool.

If you already have Cognito set up or do not want to use the Amplify CLI to generate Cognito resources, you can follow the documentation in the existing resources tab or check out the code snippet below.

If you are manually setting up an identity pool in the Cognito console you can follow this guide. When setting up the identity pool ensure that access to unauthenticated identities is enabled.

When initially configuring Amplify you can pass in the cognito region and an identity pool instead of using the Amplify generated aws-exports file.

import React from 'react';
import { ThemeProvider } from '@aws-amplify/ui-react';
import { Amplify } from 'aws-amplify';
import '@aws-amplify/ui-react/styles.css';
import awsexports from './aws-exports';

Amplify.configure({
   ...awsexports,
  "aws_cognito_region": "us-east-2", // (required) - Region where Amazon Cognito project was created
  "aws_cognito_identity_pool_id": "us-east-2:xxx-xxx-xxx-xxx-xxx", // (required) - the pool region should match the cognito region
});

export default function App() {
  return (
    <ThemeProvider>
    </ThemeProvider>
  );
}

Use this option if you want more control over the process of obtaining AWS credentials.

By default, FaceLivenessDetector uses Amplify Auth to authorize users to perform the Face Liveness check. You can use your own credentials provider to retrieve credentials from Amazon Cognito or assume a role with Amazon STS, for example:

import { FaceLivenessDetectorCore, AwsCredentialProvider } from '@aws-amplify/ui-react-liveness';
 
const credentialProvider: AwsCredentialProvider = async () => {
  // Fetch the credentials
}

return (
  <FaceLivenessDetectorCore
    sessionId={'<sessionId>'}
    region={'<region>'}
    onAnalysisComplete={() => {}}
    onError={onError}
    config={{ credentialProvider }}
  />
);

Note: The provided Credentials Provider's fetchAWSCredentials function is called once at the start of the liveness flow, with no token refresh.

Update IAM Role Permissions

Now that you have Amplify Auth setup, follow the steps below to create an inline policy to enable authenticated app users to access Rekognition.

  1. Go to AWS IAM console → Roles

  2. Select the newly created unauthRole for your project (amplify-<project_name>-<env_name>-<id>-unauthRole if using the Amplify CLI). Note that unauthRole should be used if you are not logging in, but if you are using an authenticator with your application, you will need to use authRole.

  3. Choose Add Permissions, then select Create Inline Policy, then choose JSON and paste the following:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "rekognition:StartFaceLivenessSession",
            "Resource": "*"
        }
    ]
}
  1. Choose Review Policy

  2. Name the policy

  3. Choose Create Policy

To use Amplify UI FaceLivenessDetector, you must also set up a backend to create the Face Liveness session and retrieve the session results. Follow the Amazon Rekognition Face Liveness developer guide to set up your backend.

Step 2. Install dependencies

npm install @aws-amplify/ui-react-liveness aws-amplify
yarn add @aws-amplify/ui-react-liveness aws-amplify

Step 3. Initialize Amplify

Next.js 13.4+ introduces App Router with the usage of Server Components. Amplify UI components are interactive and designed to work on the client side. To use them inside of Server Components you must wrap them in a Client Component with "use client". For more info, visit Next.js third party package documentation.

If you are using Next.js Pages Router, no changes are required to use Amplify UI components.

import React from 'react';
import { ThemeProvider } from '@aws-amplify/ui-react';
import { Amplify } from 'aws-amplify';
import '@aws-amplify/ui-react/styles.css';
import awsexports from './aws-exports';

Amplify.configure(awsexports);

export default function App() {
  return (
    <ThemeProvider>
    </ThemeProvider>
  );
}

Step 4. Add FaceLivenessDetector

To get started you will need to make a request to your backend to receive a sessionId and pass that to the FaceLivenessDetector component.

Once a valid sessionId, region, and callback has been passed, FaceLivenessDetector will take care of streaming video and presenting Face Liveness challenges.

import React from 'react';
import { FaceLivenessDetector } from '@aws-amplify/ui-react-liveness';
import { Loader, ThemeProvider } from '@aws-amplify/ui-react';

export function LivenessQuickStartReact() {
  const [loading, setLoading] = React.useState<boolean>(true);
  const [createLivenessApiData, setCreateLivenessApiData] = React.useState<{
    sessionId: string;
  } | null>(null);

  React.useEffect(() => {
    const fetchCreateLiveness: () => Promise<void> = async () => {
      /*
       * This should be replaced with a real call to your own backend API
       */
      await new Promise((r) => setTimeout(r, 2000));
      const mockResponse = { sessionId: 'mockSessionId' };
      const data = mockResponse;

      setCreateLivenessApiData(data);
      setLoading(false);
    };

    fetchCreateLiveness();
  }, []);

  const handleAnalysisComplete: () => Promise<void> = async () => {
    /*
     * This should be replaced with a real call to your own backend API
     */
    const response = await fetch(
      `/api/get?sessionId=${createLivenessApiData.sessionId}`
    );
    const data = await response.json();

    /*
     * Note: The isLive flag is not returned from the GetFaceLivenessSession API
     * This should be returned from your backend based on the score that you
     * get in response. Based on the return value of your API you can determine what to render next.
     * Any next steps from an authorization perspective should happen in your backend and you should not rely
     * on this value for any auth related decisions.
     */
    if (data.isLive) {
      console.log('User is live');
    } else {
      console.log('User is not live');
    }
  };

  return (
    <ThemeProvider>
      {loading ? (
        <Loader />
      ) : (
        <FaceLivenessDetector
          sessionId={createLivenessApiData.sessionId}
          region="us-east-1"
          onAnalysisComplete={handleAnalysisComplete}
          onError={(error) => {
            console.error(error);
          }}
        />
      )}
    </ThemeProvider>
  );
}
import React from 'react';
import { FaceLivenessDetector } from '@aws-amplify/ui-react-liveness';
import { Loader, ThemeProvider } from '@aws-amplify/ui-react';

export function LivenessQuickStartReact() {
  const [loading, setLoading] = React.useState(true);
  const [createLivenessApiData, setCreateLivenessApiData] =
    React.useState(null);

  React.useEffect(() => {
    const fetchCreateLiveness = async () => {
      /*
       * This should be replaced with a real call to your own backend API
       */
      await new Promise((r) => setTimeout(r, 2000));
      const mockResponse = { sessionId: 'mockSessionId' };
      const data = mockResponse;

      setCreateLivenessApiData(data);
      setLoading(false);
    };

    fetchCreateLiveness();
  }, []);

  const handleAnalysisComplete = async () => {
    /*
     * This should be replaced with a real call to your own backend API
     */
    const response = await fetch(
      `/api/get?sessionId=${createLivenessApiData.sessionId}`
    );
    const data = await response.json();

    /*
     * Note: The isLive flag is not returned from the GetFaceLivenessSession API
     * This should be returned from your backend based on the score that you
     * get in response. Based on the return value of your API you can determine what to render next.
     * Any next steps from an authorization perspective should happen in your backend and you should not rely
     * on this value for any auth related decisions.
     */
    if (data.isLive) {
      console.log('User is live');
    } else {
      console.log('User is not live');
    }
  };

  return (
    <ThemeProvider>
      {loading ? (
        <Loader />
      ) : (
        <FaceLivenessDetector
          sessionId={createLivenessApiData.sessionId}
          region="us-east-1"
          onAnalysisComplete={handleAnalysisComplete}
          onError={(error) => {
            console.error(error);
          }}
        />
      )}
    </ThemeProvider>
  );
}

See Rekognition documentation for best practices when using FaceLivenessDetector.

Full API Reference

FaceLivenessDetectorProps

Below is the full list of props that can be used with the FaceLivenessDetector component.

NameDescriptionType
sessionIdThe sessionId as returned by CreateFaceLivenessSession API.
string
onAnalysisCompleteCallback that signals when the liveness session has completed analysis. At this point a request can be made to GetFaceLivenessSessionResults.
() => Promise<void>
regionThe AWS region to stream the video to, this should match the region you called the CreateFaceLivenessSession API in.
string
onUserCancel?Callback called when the user cancels the flow. This callback is also called when users click the "Try Again" button in the default error modal.
() => void
onError?Callback called when there is error occured on any step.
(error: LivenessError) => void
disableStartScreen?Optional parameter for the disabling the start screen, default: false.
boolean
components?Optional object for overriding some UI components.
FaceLivenessDetectorComponents
displayText?Optional object for internationalizing strings.
LivenessDisplayText
config?Optional parameter for advanced options for the component.
FaceLivenessDetectorConfig

FaceLivenessDetectorComponents

Below is the full list of props that can be used with the FaceLivenessDetectorComponents. You can also reference the example here.

NameDescriptionType
PhotosensitiveWarning?Overrides the rendered component for the photosensitivity warning.
React.ComponentType
ErrorView?Overrides the rendered component for error view.
React.ComponentType

FaceLivenessDetectorConfig

Below is the full list of props that can be used with the FaceLivenessDetectorConfig. For instructions on using your own CDN check here.

NameDescriptionType
binaryPath?Overrides the WASM binary path, the default is https://cdn.liveness.rekognition.amazonaws.com/face-detection/tensorflow/tfjs-backend-wasm/3.11.0/. When overriding this path ensure that the wasm version matches the version of @tensorflow/tfjs-backend-wasm installed by npm.
string
faceModelUrl?Overrides the Blazeface model and weights bin CDN URL. Default value is https://cdn.liveness.rekognition.amazonaws.com/face-detection/tensorflow-models/blazeface/0.0.7/model/model.json
string

FaceLivenessDetectorCoreConfig

Below is the full list of props that can be used with the FaceLivenessDetectorCoreConfig. This config can only be used with the <FaceLivenessDetectoreCore /> component.

NameDescriptionType
binaryPath?Overrides the WASM binary path, the default is https://cdn.liveness.rekognition.amazonaws.com/face-detection/tensorflow/tfjs-backend-wasm/4.11.0/. When overriding this path ensure that the wasm version matches the version of @tensorflow/tfjs-backend-wasm installed by npm.
string
faceModelUrl?Overrides the Blazeface model and weights bin CDN URL. Default value is https://cdn.liveness.rekognition.amazonaws.com/face-detection/tensorflow-models/blazeface/1.0.2/model/model.json
string
credentialProvider?An optional callback that provides AWS Credentials.
AwsCredentialProvider

LivenessError

Below is the LivenessError type used in the onError function that should give you more granularity into the types of errors happening in the component.

NameDescriptionType
stateThe LivenessErrorState value which indicates the general error type as seen from the component.
LivenessErrorState
errorThe error object containing the more specific error name and stack trace.
Error

LivenessErrorState

Below is the full list of error states that can be returned from the onError prop.

NameDescriptionType
RUNTIME_ERRORIndicates an error that occurs in the component runtime.
Error
SERVER_ERRORIndicates an error occurred from the Rekognition streaming API or in the onAnalysisComplete callback.
Error
CONNECTION_TIMEOUTIndicates a timeout occurred during the initial websocket connection.
Error
TIMEOUTIndicates a timeout occurred when user attempted a liveness check.
Error
FACE_DISTANCE_ERRORIndicates that the user moved their face too close to the camera before the check started.
Error
CAMERA_ACCESS_ERRORIndicates that an error occurred when attempting to access the user's camera, this could be because they did not allow camera permissions in the browser.
Error
CAMERA_FRAMERATE_ERRORIndicates that the provided camera does not meet the minimum framerate requirements for a liveness check.
Error
FRESHNESS_TIMEOUTIndicates that the component timed out when attempting to determine freshness of the video via colors flashing on the screen.
Error
MOBILE_LANDSCAPE_ERRORIndicates that the user attempted to switch to using landscape mode which is not supported.
Error

LivenessDisplayText

The text in FaceLivenessDetector is defined as string resources in the component's displayText.ts file.

Amplify open source software, documentation and community are supported by Amazon Web Services.

© 2024 Amazon Web Services, Inc. and its affiliates. All rights reserved. View the site terms and privacy policy.

Flutter and the related logo are trademarks of Google LLC. We are not endorsed by or affiliated with Google LLC.