SafetyNet reCAPTCHA API

SafetyNet サービスには、悪意のあるトラフィックからアプリを保護する reCAPTCHA API が含まれています。

reCAPTCHA は、高度なリスク分析エンジンを使用して、スパムやその他の攻撃からアプリを保護する無料サービスです。このサービスは、アプリを操作しているのが人間ではなくボットであるという疑いがある場合に、アプリの実行を継続するにあたって人間が解答しなければならない CAPTCHA を提供します。

このドキュメントでは、SafetyNet の reCAPTCHA API をアプリに統合する方法について説明します。

追加利用規約

ReCAPTCHA API にアクセスするか、またはこれを使用すると、Google API 利用規約および下記の追加利用規約に同意したものと見なされます。 適用されるすべての利用規約とポリシーを確認し、理解したうえで API にアクセスしてください。

reCAPTCHA 利用規約

お客様は、reCAPTCHA API がその機能を実行するためにハードウェアおよびソフトウェアの情報(デバイスおよびアプリケーションのデータ、整合性チェックの結果など)を収集し、分析のためにそのデータを Google に送信することを理解し、了承するものとします。お客様は、Google API 利用規約第 3 条(d)に基づき、この API を利用するにあたり、お客様の責任において、これらのデータの収集および Google との共有に関して必要な告知を行い、ユーザーの同意を得ることに合意するものとします。

reCAPTCHA キーペアを登録する

SafetyNet reCAPTCHA API で使用するキーペアを登録するには、reCAPTCHA Android 登録サイトにアクセスして、次の手順を実施します。

  1. 表示されたフォームに、次の情報を入力します。

    • [ラベル]: キーの一意なラベル。通常、会社や組織の名前を使用します。
    • [パッケージ名]: この API キーを使用する各アプリのパッケージ名を指定します。アプリで API を使用するには、入力したパッケージ名が該当アプリのパッケージ名と完全に一致する必要があります。パッケージ名は 1 行に 1 つずつ入力します。
    • [アラートをオーナーに送信する]: reCAPTCHA API に関するメールを受信する場合は、このチェックボックスをオンにします。
  2. [reCAPTCHA 利用条件に同意する] チェックボックスをオンにしてから、[登録] をクリックします。

  3. 次に表示されるページの [アプリに reCAPTCHA を追加する] セクションで、公開鍵と秘密鍵がそれぞれ [サイトキー] と [シークレット キー] に表示されます。サイトキーは検証リクエストを送信するときに使用し、シークレット キーはユーザー応答トークンを検証するときに使用します。

SafetyNet API の依存関係を追加する

reCAPTCHA API を使用する前に、SafetyNet API をプロジェクトに追加する必要があります。Android Studio を使用している場合、Gradle の依存関係にこの API を選択的に組み込むには、次のコード スニペットに示されているビルドルールをインクルードする必要があります。

    apply plugin: 'com.android.application'
    ...
    dependencies {
        compile 'com.google.android.gms:play-services-safetynet:17.0.0'
    }
    

詳細については、Google Play 開発者サービスのセットアップをご覧ください。

reCAPTCHA API を使用する

このセクションでは、reCAPTCHA API を呼び出して CAPTCHA 検証リクエストを送信し、ユーザー応答トークンを受信する方法について説明します。

検証リクエストを送信する

SafetyNet reCAPTCHA API を呼び出すには、verifyWithRecaptcha() メソッドを呼び出します。通常、このメソッドは、アクティビティ内のボタンなどの UI 要素をユーザーが選択することに対応しています。

アプリで verifyWithRecaptcha() メソッドを使用する場合は、以下を行う必要があります。

  • API サイトキーをパラメータとして渡す。
  • onSuccess() メソッドと onFailure() メソッドをオーバーライドして、検証リクエスト タスクの結果(成功または失敗)を両方とも処理する。特に、API が onFailure()ApiException のインスタンスを渡した場合、getStatusCode() で取得できる各ステータス コードに対応する処理を行う必要があります。詳細については、通信エラーを処理するをご覧ください。

このメソッドを呼び出す方法を次のコード スニペットに示します。

Kotlin

    fun onClick(view: View) {
        SafetyNet.getClient(this).verifyWithRecaptcha(YOUR_API_SITE_KEY)
                .addOnSuccessListener(this as Executor, OnSuccessListener { response ->
                    // Indicates communication with reCAPTCHA service was
                    // successful.
                    val userResponseToken = response.tokenResult
                    if (response.tokenResult?.isNotEmpty() == true) {
                        // Validate the user response token using the
                        // reCAPTCHA siteverify API.
                    }
                })
                .addOnFailureListener(this as Executor, OnFailureListener { e ->
                    if (e is ApiException) {
                        // An error occurred when communicating with the
                        // reCAPTCHA service. Refer to the status code to
                        // handle the error appropriately.
                        Log.d(TAG, "Error: ${CommonStatusCodes.getStatusCodeString(e.statusCode)}")
                    } else {
                        // A different, unknown type of error occurred.
                        Log.d(TAG, "Error: ${e.message}")
                    }
                })
    }
    

Java

    public void onClick(View v) {
        SafetyNet.getClient(this).verifyWithRecaptcha(YOUR_API_SITE_KEY)
            .addOnSuccessListener((Executor) this,
                new OnSuccessListener<SafetyNetApi.RecaptchaTokenResponse>() {
                    @Override
                    public void onSuccess(SafetyNetApi.RecaptchaTokenResponse response) {
                        // Indicates communication with reCAPTCHA service was
                        // successful.
                        String userResponseToken = response.getTokenResult();
                        if (!userResponseToken.isEmpty()) {
                            // Validate the user response token using the
                            // reCAPTCHA siteverify API.
                        }
                    }
            })
            .addOnFailureListener((Executor) this, new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        if (e instanceof ApiException) {
                            // An error occurred when communicating with the
                            // reCAPTCHA service. Refer to the status code to
                            // handle the error appropriately.
                            ApiException apiException = (ApiException) e;
                            int statusCode = apiException.getStatusCode();
                            Log.d(TAG, "Error: " + CommonStatusCodes
                                    .getStatusCodeString(statusCode));
                        } else {
                            // A different, unknown type of error occurred.
                            Log.d(TAG, "Error: " + e.getMessage());
                        }
                    }
            });
    }
    

ユーザー応答トークンを検証する

ユーザーが CAPTCHA チャレンジに成功すると、reCAPTCHA API は onSuccess() メソッドを実行します。ただし、このメソッドは、ユーザーが CAPTCHA に正しく答えたことを示しているにすぎません。次に、バックエンド サーバーからのユーザーの応答トークンを検証する必要があります。

ユーザーの応答トークンを検証する方法については、ユーザーの応答を検証するをご覧ください。

通信エラーを処理する

アプリが reCAPTCHA サービスと正常に通信できない場合は、API でエラーが発生している可能性があります。このようなエラーを適切に処理するロジックをアプリに追加する必要があります。また、エラーが発生したときに、メッセージを表示して、アプリが CAPTCHA 応答の処理を完了できない理由を説明する必要があります。

一般的な API エラーのステータス コードを次に示します。

RECAPTCHA_INVALID_SITEKEY

サイトキーが無効です。API キーを正しく登録していることと、API の呼び出し時にパラメータとして渡すサイトキーが正しくコピーされていることを確認してください。

定数値: 12007

RECAPTCHA_INVALID_KEYTYPE

サイトキーのタイプが無効です。reCAPTCHA Android の登録サイトに移動して、新しいサイトキーを作成してください。

定数値: 12008

RECAPTCHA_INVALID_PACKAGE_NAME

呼び出し元のアプリのパッケージ名が、サイトキーに関連付けた名前と一致しません。呼び出し元のアプリのパッケージ名を reCAPTCHA 管理コンソールのサイトキーに追加するか、サイトキーのパッケージ名検証を無効にしてください。

定数値: 12013

UNSUPPORTED_SDK_VERSION

API は、このデバイスの Android SDK バージョンでサポートされていません。新しいバージョンの Android SDK にアップグレードしてから、再度、API との通信を試してください。

定数値: 12006

TIMEOUT

API が応答を待っている間に、ユーザーが CAPTCHA を操作しなかったため、あるいは CAPTCHA の読み込み処理自体がタイムアウトしたため、セッションがタイムアウトになりました。ユーザーが API を再度呼び出すのを待ってください。その間に、アプリを続行するには CAPTCHA を完了する必要があることをユーザーに伝えられます。

定数値: 15

NETWORK_ERROR

インターネットに接続されていません。接続を確認してから、再度 API との通信を試してください。

定数値: 7

ERROR

オペレーション中に一般的なエラーが発生しました。

定数値: 13

reCAPTCHA API が返すステータス コードの詳細については、SafetyNetStatusCodes リファレンスをご覧ください。