Amazon Web Services ブログ

AWS Amplify と Face Liveness で正しいユーザーを検出する

なりすましや悪質業者の世界では、AWS AmplifyAmplify UI FaceLivenessDetector コンポーネントが、本物のユーザーによってアプリが使用されているか確認するのに役立ちます。この一連のコンポーネントライブラリは、Amazon Rekognition Face Liveness の機能を利用しています。機械学習や人工知能 (AI) の経験は必要ありません。

この完全にマネージドな機能は、なりすましを検出するのに利用する自分の顔を撮るために正面カメラを使用します。いくつかの簡単なステップで、React、Android、Swift アプリケーションにこの機能を追加できます。

このチュートリアルでは、アプリケーションにサインアップしたユーザーを認証する方法を紹介します。そのために新しいNext.js アプリを作成し、Amplify を設定し、認証機能を追加し、FaceLivenessDetector コンポーネントを追加します。AWS Lambda REST API を使用して、Amazon Rekognition Liveness の機能と通信するエンドポイントを作成します。これらのエンドポイントは、ユーザーが本物かどうかを判断するのに役立つスコアを返却します。

前提条件

このチュートリアルでは以下のものが必要となります。

アプリと権限の設定

まず、新しい Next.js アプリケーションを作成しましょう!このチュートリアルでは npm を使いますが、お好きなパッケージマネージャを使ってください。

$ npx create-next-app@latest --no-app

このアプリケーションでは、Amplify で必要に応じて使用できる App Router は使用しません。Amplify で App Router を使用する際の詳細については、Amplify UI Docs をご覧ください。

新しくできた Next アプリのディレクトリへ移動し、Amplify ライブラリをインストールします。

$ npm i @aws-amplify/ui-react-liveness @aws-amplify/ui-react aws-amplify

まだインストールしていない場合は、Amplify CLI もインストールします。

$ npm i @aws-amplify/cli -g

この先の手順には AWS アカウントが必要です。こちらからサインアップすることができます。また、初めて Amplify CLI を使用する場合は、必ず amplify configure を実行してください。

Next アプリが Amplify を認識するように設定しましょう。ここでは CLI を使いますが、Amplify Studio を使うこともできます。

init コマンドを実行します。

amplify init
? Enter a name for the project livenessnextexampleg
The following configuration will be applied:

Project information
| Name: livenessnextexampleg
| Environment: dev
| Default editor: Visual Studio Code
| App type: javascript
| Javascript framework: react
| Source Directory Path: src
| Distribution Directory Path: build
| Build Command: npm run-script build
| Start Command: npm run-script start

? Initialize the project with the above configuration? Yes
Using default provider awscloudformation
? Select the authentication method you want to use: AWS profile

全ての項目でデフォルトを選択し、進めることができます。こちらの手順でアプリ内に amplify フォルダが作成され、src フォルダ内に aws-exports ファイルが作成されます。

Liveness のための認証機能を追加

認証されたユーザのみ FaceLivenessDetector コンポーネントを使用できるように、Auth カテゴリを追加しましょう。これにより、あなたのアカウントの下に Amazon Cognito ユーザーと ID プールが作成されます。

以下のコマンドを実行してください。

$ amplify add auth

電子メールとその他全ての設問をデフォルトの設定で選択します。

必ず変更をプッシュしてください!

$ amplify push

認証されていないユーザに Liveness の使用を許可する場合は、代わりに Manual Configurationを選択することをお勧めします。最も重要なプロンプトは Allow unauthenticated logins です。ここでは必ず Yes を選択してください。これでログインせずに Liveness サービスを使用できるようになります。また、未認証ロールの正しい権限をセットアップする必要があります。IAM 権限のセットアップで、authRole の代わりに amplify-<project_name>-<env_name>-<id>-unauthRole を更新します。IAM 権限のセットアップ方法の詳細は次のセクションで説明します。

IAM 権限の設定

認証機能の追加後、IAM ロールを少し変更する必要があります。authRole に Amazon Rekognition Face Liveness サービスへのアクセス権を与える必要があります。このロールはフロントエンドの権限として使用されます。

console コマンドを実行して AWS コンソールを開きます。

$ amplify console

マネジメントコンソールが開いたら、IAM を検索して開きます。

Roles をクリックし、あなたのために作成された Amplify ロールを検索してクリックします。これは、amplify-<project_name>-<env_name>-<id>-authRole という形式になっており、 <project_name><env_name><id> を自分の情報に置き換えて検索してください。

Add Permissions を選択し、Create Inline Policy を選択し、JSON タブを選択し、以下を貼り付けます。

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

これにより、Rekognition サービスの開始、作成、および結果の取得の権限のみが与えられます。次に Review Policy を選択し、Create Policy を選択します。

AWS Lambda バックエンド

権限と認証の設定ができたので、バックエンドアプリケーションを作成しましょう。Express を実行する Node.js の AWS Lambda Function を使用して REST API を追加します。Express クライアントを使用して、いくつかのエンドポイントをセットアップし、顔検出の結果を取得します。

ターミナルを開き、add api コマンドを実行します。

$ amplify add api

以下のオプションを選択してください。必ず/session エンドポイントを追加し、テンプレートとして Serverless ExpressJS functionを選択してください。選択したカテゴリのラベルを記録しておいてください。後ほどフロントエンドのコードと接続するときに必要になります。

? Select from one of the below mentioned services: REST
✔ Provide a friendly name for your resource to be used as a label for this category in the project: ·liveness
✔ Provide a path (e.g., /book/{isbn}): · /session
Only one option for [Choose a Lambda source]. Selecting [Create a new Lambda function].
? Provide an AWS Lambda function name: liveness
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: Serverless ExpressJS function (Integration with API Gateway)

Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation
- Lambda layers configuration
- Environment variables configuration
- Secret values configuration

? Do you want to configure advanced settings? No
? Do you want to edit the local lambda function now? Yes

API Gateway とLambda Function 用の新しいフォルダがいくつか生成されます。

新しいライブラリを追加することから始めていきましょう。amplify/backend/function/liveness/src フォルダに移動し、以下のコマンドを実行して Rekognition クライアントの正しい依存関係をインストールします。

$ npm i @aws-sdk/client-rekognition

先ほど作成した関数を更新する必要があります。amplify/backend/function/liveness/src フォルダに移動します。utils フォルダを追加し、getRekognitionClient.js という新しいファイルを作成します。

以下のコードを追加します。このコードは Amplify アプリケーションを設定し、新しい Rekognition クライアントを作成しています。

const { Rekognition } = require("@aws-sdk/client-rekognition");

const getRekognitionClient = () => {
  const rekognitionClient = new Rekognition({
    region: 'us-east-1'
  });

  return rekognitionClient;
};

module.exports = getRekognitionClient;

上記のコードスニペットのregionをあなたのリージョンに合わせて更新してください。リージョンはバックエンドとフロントエンドのコード間で一致していなければならず、FAQ に示されているように、そのリージョンで liveness が利用可能でなければなりません。

amplify/backend/function/liveness/src フォルダで app.js ファイルを開いてください。いくつかの GET、POST、PUT、DELETE のサンプル関数が表示されます。サンプル関数は削除してかまいません。独自の関数を追加します。

ファイルの先頭に import を追加します。これで、先ほど作成したユーティリティ関数を取り込むことができます。

const getRekognitionClient = require("./utils/getRekognitionClient");

create エンドポイントと get エンドポイントを追加しましょう。create エンドポイントは新しい Liveness セッションを作成し、フロントエンドに返却します。get エンドポイントは信頼値を計算し、返却します。

app.get("/session/create", async function (req, res) {
  const rekognition = getRekognitionClient();
  const response = await rekognition.createFaceLivenessSession({});

  return res.status(200).json({
    sessionId: response.SessionId,
  });
});

app.get("/session/get", async function (req, res) {
  const rekognition = getRekognitionClient();
  const response = await rekognition.getFaceLivenessSessionResults({
    SessionId: req.query.sessionId,
  });

  const isLive = response.Confidence > 90;

  res.status(200).json({ isLive });
});

ここではConfidenceの値にのみ注目していますが、必要に応じて API から監査画像や参考画像の境界ボックスなど、他の値を取得することもできます。

この例では、信頼度スコアが 90 以上であれば、その画像は実際のユーザーのものであると判断します。これは厳密なルールではないので、アプリケーションやそのニーズに応じて信頼度を高くしたり低くしたりする必要があるかもしれません。また、バックエンドの他の部分に対する将来のリクエストを認可する方法として、信頼度 (Confidence) の値を使用することもできます。

最後に、正しいポリシーを設定する必要があります。こちらのファイルを開いてください。
amplify/backend/function/liveness/custom-policies.json

こちらのポリシーを入力してください 。これで Lambda は Liveness セッションの作成と結果取得のみできるようになります。

[
  {
    "Action": [
      "rekognition:CreateFaceLivenessSession",
      "rekognition:GetFaceLivenessSessionResults"
    ],
    "Resource": ["*"]
  }
]

このファイルを保存し、変更をプッシュアップしてください!

$ amplify push

フロントエンドのコードに移りましょう!

Next.js フロントエンド

バックエンドが完成したので、次はフロントエンドのサインアップページを作成します。

Amplify Authenticator コンポーネントと FaceLivenessDetector を使用して、このプロセスをより簡単にします。

Next.js を利用する Amplify の設定

_app.tsx ファイルを開き、以下のコードを追加しましょう。

import type { AppProps } from "next/app";
import { Amplify } from "aws-amplify";
import { withAuthenticator } from "@aws-amplify/ui-react";
import "@aws-amplify/ui-react/styles.css";
import awsExports from "../aws-exports";
Amplify.configure(awsExports);

function App({ Component, pageProps }: AppProps) {
  return <Component {...pageProps} />;
}

export default withAuthenticator(App);

withAuthenticator 高階コンポーネントは、アプリケーション全体をラップし、サインインしたユーザーだけが先に進めるようにします。また、Amplify.configure(awsExports) を実行してフロントエンドを設定し、先ほど追加した AWS の認証サービスとやり取りができるようにします。最後に、@aws-amplify/ui-react/styles.css からスタイルをインポートします。

Next アプリケーションを起動すると、このようなログインページが表示されます。

Authenticator

Authenticator

続けて、srccomponents という新しいフォルダを作成し、その中に Liveness.tsx という新しいファイルを追加します。

以下のコードを追加します。

import { useEffect, useState } from "react";
import { Loader, Heading } from "@aws-amplify/ui-react";
import { FaceLivenessDetector } from "@aws-amplify/ui-react-liveness";
import { API } from "aws-amplify";

export function LivenessQuickStart() {
  const [loading, setLoading] = useState<boolean>(true);
  const [sessionId, setSessionId] = useState<{
    sessionId: string;
  } | null>(null);
  const [success, setSuccess] = useState('');

  useEffect(() => {
    const fetchCreateLiveness = async () => {
      const response = await API.get("liveness", "/session/create", {});
      setSessionId(response);
      setLoading(false);
    };

    fetchCreateLiveness();
  }, []);

  const handleAnalysisComplete = async () => {

    const data = await API.get("liveness", "/session/get", {
      queryStringParameters: {
        sessionId: sessionId?.sessionId,
      },
    });

    if (data.isLive) {
      setSuccess("User is live");
      console.log("live");
    } else {
      setSuccess("User is not live");
      console.log("not live");
    }
  };

  const handleError = (error: Error) => {
    console.log("got error", error);
  };
  return (
    <>
      {loading ? (
        <Loader />
      ) : (
        <>
          <FaceLivenessDetector
            sessionId={sessionId?.sessionId ?? "1"}
            region="us-east-1"
            onAnalysisComplete={handleAnalysisComplete}
            onError={handleError}
          />
          <Heading level={2}>{success}</Heading>
        </>
      )}
    </>
  );
}

上記コードのregionをあなたが利用しているリージョンに合わせて変更してください。リージョンはバックエンドで使用しているものと同じでなければなりません。

このコードはページが読み込みされるとすぐに /session/create を呼び出し、セッション情報を取得して createLivenessApiData useState に保存します。また、ローディングスピナーも削除します。

liveness は、REST api を追加したときに設定した API Gateway の名前です。この文字列は、選択した API Gateway に合わせて自由に変更してください。この値は aws-exports ファイルの aws_cloud_logic_custom にも記載されています。

handleAnalysisComplete 関数は、sessionId を使って /session/get エンドポイントを呼び出し、信頼度スコア を返します。これは、次に何をすべきか決定するのに役立ちます。

このチュートリアルでは、返されたスコアに応じてユーザーがいるかユーザーがいないのかをコンソールログに出力します。実世界の状況では、これを別の方法で処理したくなるかもしれませんし、スコアが低すぎる場合はユーザーに再試行させたくなるかもしれません。

最後に、この新しい Liveness コンポーネントをアプリケーションに追加してみましょう。index.tsx ファイルを開き、以下のコードを追加します。

import { LivenessQuickStart } from "@/components/Liveness";
import { Button, useAuthenticator, View } from "@aws-amplify/ui-react";

export default function Home() {
  const { signOut } = useAuthenticator((context) => [context.signOut]);
  return (
      <View width="600px" margin="0 auto">
        <LivenessQuickStart />
        <Button onClick={signOut} variation="warning">
          Sign Out
        </Button>
      </View>
  );
}

全部試してみましょう!

テストする

すべてのコードを更新した後、Next アプリを起動し、localhost:3000 を開いて Create Account タブをクリックし、新規ユーザーを作成します。

サインアップ後、このページが表示されます。

顔検証の手順

このページが表示されない場合は、このページに影響を与えている可能性があるグローバルスタイルをすべて消去する必要があるかもしれません。

Begin check ボタンをクリックします。すると、もっと近づくように指示されます。あなたの顔が楕円で完全に埋まるように、できるだけ近づいてください。

楕円状の顔チェック

すべてがうまくいけば、いくつかのフラッシュが表示され、コンソールにスコアが返されます!ページを更新して再挑戦することもできます。

クリーンアップ

アプリケーションの検証が終わったら、amplify delete を実行することで全てのリソースを削除することができます。

まとめ

このチュートリアルでは、Next.js と REST API を使って Amplify Face Liveness コンポーネントをセットアップする方法を見てきました。Liveness についてさらに学びたい場合は、公式ドキュメントをご覧ください。そこから、国際化対応テーマ設定など、FaceLivenessDetector コンポーネントを完全にカスタマイズする方法について学ぶことができます。

Amplify についてもっと知りたい方はドキュメントをご覧ください。また、AWS の無料枠で Amplify を試すこともできます。

私についての情報は Twitter の ErikCH で見ることができます!

この記事は、Detect real users with AWS Amplify and Face Liveness を翻訳したものです。

翻訳はSolutions Architect の Takuya Setaka が担当しました。