このページでは、返された完全性判定の結果の解釈とその対応について説明します。標準 API リクエストとクラシック API リクエストのどちらを実行しても、完全性判定の結果は同じ形式で同様の内容が返されます。完全性判定の結果は、デバイス、アプリ、アカウントの有効性に関する情報を伝えます。アプリのサーバーは、復号と検証がなされた判定結果のペイロードを使用して、アプリ内の特定のアクションまたはリクエストを処理する最善の方法を決定できます。
返される完全性判定の結果の形式
返されるペイロードは書式なしテキスト JSON であり、デベロッパー提供の情報とともに完全性シグナルを含んでいます。
ペイロードの一般的な構造は次のとおりです。
{ "requestDetails": { ... }, "appIntegrity": { ... }, "deviceIntegrity": { ... }, "accountDetails": { ... }, "environmentDetails": { ... } }
個々の完全性判定の結果を確認する前に、requestDetails フィールドの値が元のリクエストの値と一致していることを確認する必要があります。以下のセクションでは、各フィールドについて詳しく説明します。
リクエストの詳細フィールド
requestDetails フィールドにはリクエストに関する情報が含まれます。この情報にはデベロッパー提供情報が含まれ、標準リクエストの場合は requestHash、クラシック リクエストの場合は nonce にあります。
標準 API リクエストの場合:
"requestDetails": { // Application package name this attestation was requested for. // Note that this field might be spoofed in the middle of the request. "requestPackageName": "com.package.name", // Request hash provided by the developer. "requestHash": "aGVsbG8gd29scmQgdGhlcmU", // The timestamp in milliseconds when the integrity token // was requested. "timestampMillis": "1675655009345" }
これらの値は、元のリクエストの値と一致する必要があります。したがって、次のコード スニペットに示すように、requestPackageName と requestHash が元のリクエストで送信されたものと一致することを確認して、JSON ペイロードの requestDetails の部分を検証します。
Kotlin
val requestDetails = JSONObject(payload).getJSONObject("requestDetails") val requestPackageName = requestDetails.getString("requestPackageName") val requestHash = requestDetails.getString("requestHash") val timestampMillis = requestDetails.getLong("timestampMillis") val currentTimestampMillis = ... // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request || !requestHash.equals(expectedRequestHash) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
Java
RequestDetails requestDetails = decodeIntegrityTokenResponse .getTokenPayloadExternal() .getRequestDetails(); String requestPackageName = requestDetails.getRequestPackageName(); String requestHash = requestDetails.getRequestHash(); long timestampMillis = requestDetails.getTimestampMillis(); long currentTimestampMillis = ...; // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. || !requestHash.equals(expectedRequestHash) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
クラシック API リクエストの場合:
"requestDetails": { // Application package name this attestation was requested for. // Note that this field might be spoofed in the middle of the // request. "requestPackageName": "com.package.name", // base64-encoded URL-safe no-wrap nonce provided by the developer. "nonce": "aGVsbG8gd29scmQgdGhlcmU", // The timestamp in milliseconds when the request was made // (computed on the server). "timestampMillis": "1617893780" }
これらの値は、元のリクエストの値と一致する必要があります。したがって、次のコード スニペットに示すように、requestPackageName と nonce が元のリクエストで送信されたものと一致することを確認して、JSON ペイロードの requestDetails の部分を検証します。
Kotlin
val requestDetails = JSONObject(payload).getJSONObject("requestDetails") val requestPackageName = requestDetails.getString("requestPackageName") val nonce = requestDetails.getString("nonce") val timestampMillis = requestDetails.getLong("timestampMillis") val currentTimestampMillis = ... // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. See 'Generate a nonce' // section of the doc on how to store/compute the expected nonce. || !nonce.equals(expectedNonce) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
Java
JSONObject requestDetails = new JSONObject(payload).getJSONObject("requestDetails"); String requestPackageName = requestDetails.getString("requestPackageName"); String nonce = requestDetails.getString("nonce"); long timestampMillis = requestDetails.getLong("timestampMillis"); long currentTimestampMillis = ...; // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. See 'Generate a nonce' // section of the doc on how to store/compute the expected nonce. || !nonce.equals(expectedNonce) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
アプリの完全性フィールド
appIntegrity フィールドにはパッケージに関する情報が含まれます。
"appIntegrity": { // PLAY_RECOGNIZED, UNRECOGNIZED_VERSION, or UNEVALUATED. "appRecognitionVerdict": "PLAY_RECOGNIZED", // The package name of the app. // This field is populated iff appRecognitionVerdict != UNEVALUATED. "packageName": "com.package.name", // The sha256 digest of app certificates (base64-encoded URL-safe). // This field is populated iff appRecognitionVerdict != UNEVALUATED. "certificateSha256Digest": ["6a6a1474b5cbbb2b1aa57e0bc3"], // The version of the app. // This field is populated iff appRecognitionVerdict != UNEVALUATED. "versionCode": "42" }
appRecognitionVerdict は次のいずれかの値を取ります。
PLAY_RECOGNIZED- アプリと証明書が、Google Play で配信されているバージョンと一致します。
UNRECOGNIZED_VERSION- 証明書またはパッケージ名が Google Play の記録と一致しません。
UNEVALUATED- アプリの完全性は評価されませんでした。デバイスの信頼性が十分でないなど、要件が満たされていませんでした。
作成したアプリによってトークンが生成されたことを確認するには、次のコード スニペットに示すように、アプリの完全性が期待どおりであることを検証します。
Kotlin
val appIntegrity = JSONObject(payload).getJSONObject("appIntegrity") val appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict") if (appRecognitionVerdict == "PLAY_RECOGNIZED") { // Looks good! }
Java
JSONObject appIntegrity = new JSONObject(payload).getJSONObject("appIntegrity"); String appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict"); if (appRecognitionVerdict.equals("PLAY_RECOGNIZED")) { // Looks good! }
アプリのパッケージ名、アプリのバージョン、アプリの証明書を手動で確認することもできます。
デバイスの完全性フィールド
deviceIntegrity フィールドには deviceRecognitionVerdict という値のみが含まれます。この値には、デバイスがアプリの完全性をどの程度強化できるかを表すラベルが 1 つ以上含まれています。デバイスがどのラベルの条件も満たしていない場合、deviceIntegrity フィールドには deviceRecognitionVerdict が含まれません。
"deviceIntegrity": { // "MEETS_DEVICE_INTEGRITY" is one of several possible values. "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"] }
デフォルトでは、deviceRecognitionVerdict に含めることができる値は以下のとおりです。
MEETS_DEVICE_INTEGRITY- アプリは、正規の認定済み Android デバイスで動作しています。Android 13 以降では、デバイスのブートローダーがロックされていることと、読み込まれた Android OS が認定済みデバイス メーカーのイメージであることを示すハードウェア格納型の証明があります。
- 空(空の値)
- アプリは、API フックなどの攻撃や root 権限取得などのシステム侵害の兆候があるデバイス、または Google Play の完全性チェックに合格していない仮想デバイス(エミュレータなど)で動作しています。
トークンが信頼できるデバイスから生成されたことを確認するには、次のコード スニペットに示すように、deviceRecognitionVerdict が期待どおりであることを検証します。
Kotlin
val deviceIntegrity = JSONObject(payload).getJSONObject("deviceIntegrity") val deviceRecognitionVerdict = if (deviceIntegrity.has("deviceRecognitionVerdict")) { deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString() } else { "" } if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) { // Looks good! }
Java
JSONObject deviceIntegrity = new JSONObject(payload).getJSONObject("deviceIntegrity"); String deviceRecognitionVerdict = deviceIntegrity.has("deviceRecognitionVerdict") ? deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString() : ""; if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) { // Looks good! }
テストデバイスがデバイスの完全性要件を満たさない問題が発生した場合は、工場出荷時の ROM がインストールされていることと、ブートローダーがロックされていることを確認してください(前者はデバイスをリセットするなどの方法で確認できます)。また、Google Play Console で Play Integrity API テストを作成することもできます。
条件付きのデバイスラベル
アプリを PC 版 Google Play Games にリリースする場合は、deviceRecognitionVerdict に次のラベルを付けることもできます。
MEETS_VIRTUAL_INTEGRITY- アプリは Google Play 開発者サービスを備えた Android エミュレータで実行されています。このエミュレータはシステム完全性チェックに合格し、Android の互換性に関する主要な要件を満たしています。
オプションのデバイス情報とデバイスの呼び出し
階層型適用戦略の一環として、オプションのデバイスラベルを受け取ることをオプトインできます。完全性判定の結果で追加ラベルを受け取ることをオプトインすると、
ラベルを
deviceRecognitionVerdictに追加できます。
MEETS_BASIC_INTEGRITY- アプリは基本的なシステム完全性チェックに合格したデバイスで動作しています。
デバイスのブートローダーはロックまたはロック解除でき、ブート状態は検証済みまたは未検証にできます。デバイスが認定されていない場合、Google はセキュリティ、プライバシー、アプリの互換性に関する保証を提供できません。Android 13 以降では、
MEETS_BASIC_INTEGRITY判定結果では、Google が提供する証明書の 信頼のルートのみが必要です。 MEETS_STRONG_INTEGRITY- アプリは、最新のセキュリティ アップデートが適用された正規の認定済み Android デバイスで動作しています。
- Android 13 以降では、
MEETS_STRONG_INTEGRITY判定結果には、Android OS パーティション パッチやベンダー パーティション パッチなど、デバイスのすべてのパーティションに対するMEETS_DEVICE_INTEGRITYと過去 1 年間のセキュリティ アップデートが必要です。 - Android 12 以前では、
MEETS_STRONG_INTEGRITY判定結果には、ブート完全性のハードウェア格納型の証明のみが必要で、デバイスに最新のセキュリティ アップデートが適用されている必要はありません 。そのため、MEETS_STRONG_INTEGRITYを使用する場合は、deviceAttributesフィールドの Android SDK バージョンも考慮することをおすすめします。
- Android 13 以降では、
ラベルのそれぞれの条件が満たされている場合、1 つのデバイスがデバイスの完全性判定の結果で複数のデバイスラベルを返します。
デバイスの属性
デバイスの属性をオプトインすることもできます。これにより、デバイスで実行されている Android OS の Android SDK バージョンを確認できます。Android SDK バージョンは、階層型適用戦略の一環として、Android 13 以降を搭載したデバイスと、それよりも低い Android SDK バージョンを搭載したデバイスを区別するのに役立ちます。今後、他のデバイス属性が追加される可能性があります。
SDK バージョンの値は、
Build.VERSION_CODES で定義されている Android SDK バージョン番号です。必要な要件が満たされていない場合、SDK バージョンは評価されません。この場合、sdkVersion フィールドは設定されないため、deviceAttributes フィールドは空になります。次のような原因が考えられます。
- デバイスの信頼性が十分でない。
- デバイスで技術的な問題が発生した。
deviceAttributes を受け取ることをオプトインした場合、deviceIntegrity フィールドには次のフィールドが追加されます。
"deviceIntegrity": { "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"], "deviceAttributes": { // 33 is one possible value, which represents Android 13 (Tiramisu). "sdkVersion": 33 } }
SDK バージョンが評価されない場合、deviceAttributes フィールドは次のように設定されます。
"deviceIntegrity": { "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"], "deviceAttributes": {} // sdkVersion field is not set. }
最近のデバイスのアクティビティ
最近のデバイスのアクティビティをオプトインすることもできます。これにより、過去 1 時間にアプリが特定のデバイスで完全性トークンをリクエストした回数を確認できます。最近のデバイスのアクティビティを使用することで、予期せぬ不審なアクティビティを過剰に行っている(アクティブな攻撃を示している可能性がある)デバイスからアプリを保護できます。 一般的なデバイスにインストールされたアプリが 1 時間ごとに完全性トークンをリクエストする回数の予測に基づいて、最近のデバイスのアクティビティの信頼レベルを決定できます。
recentDeviceActivity を受け取ることをオプトインした場合、deviceIntegrity フィールドには以下の 2 つの値が含まれるようになります。
"deviceIntegrity": { "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"], "recentDeviceActivity": { // "LEVEL_2" is one of several possible values. "deviceActivityLevel": "LEVEL_2" } }
deviceActivityLevel の定義はモードによって異なり、次のいずれかの値を取ります。
| 最近のデバイスのアクティビティ レベル | 過去 1 時間にこのデバイスでアプリがリクエストした標準 API 完全性トークン | 過去 1 時間にこのデバイスでアプリがリクエストしたクラシック API 完全性トークン |
|---|---|---|
LEVEL_1(最低) |
10 本以下 | 5 以下 |
LEVEL_2 |
11 ~ 25 | 6 ~ 10 |
LEVEL_3 |
26 ~ 50 | 11 ~ 15 |
LEVEL_4(最高) |
51 以上 | 16 以上 |
UNEVALUATED |
最近のデバイスのアクティビティは評価されませんでした。次のような原因が考えられます。
|
|
デバイスの呼び出し(ベータ版)
デバイスの呼び出しをオプトインすることもできます。これにより、特定のデバイスにカスタムのデバイスごとのデータを保存し、後で同じデバイスにアプリを再インストールしたときに確実に取得できます。完全性トークンをリクエストした後、別のサーバー間呼び出しを行って、特定のデバイスのデバイスのリコール値を変更します。
deviceRecall をオプトインした場合、deviceIntegrity フィールドには、特定のデバイスに設定したデバイスの呼び出し情報が含まれます。
"deviceIntegrity": {
"deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
"deviceRecall": {
"values": {
"bitFirst": true,
"bitSecond": false,
"bitThird": true
},
"writeDates": {
// Write time in YYYYMM format in UTC.
"yyyymmFirst": 202401,
// Note that yyyymmSecond is not set because bitSecond is false.
"yyyymmThird": 202310
}
}
}
deviceRecall は、2 つのフィールドに分かれています。
values: このデバイスに以前設定したビット値を呼び出します。writeDates: ビットの書き込み日(UTC)の正確な年月を呼び出します。呼び出すビットの書き込み日は、ビットがtrueに設定されるたびに更新され、ビットがfalseに設定されると削除されます。
デバイスの呼び出しの情報が利用できない場合、デバイスの呼び出しの値は空になります。
"deviceIntegrity": {
"deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
"deviceRecall": {
"values": {},
"writeDates": {}
}
}
アカウントの詳細フィールド
accountDetails フィールドには appLicensingVerdict という値のみが含まれます。この値は、デバイスにログインしているユーザー アカウントに対するアプリの Google Play ライセンスのステータスを表します。ユーザー アカウントにアプリの Play ライセンスがある場合、そのアプリは Google Play からダウンロードまたは購入されたものです。
"accountDetails": { // This field can be LICENSED, UNLICENSED, or UNEVALUATED. "appLicensingVerdict": "LICENSED" }
appLicensingVerdict の値は次のいずれかになります。
LICENSED- ユーザーはアプリの利用資格を持っています。つまり、ユーザーは Google Play からデバイスにアプリをインストールまたは更新しました。
UNLICENSED- ユーザーはアプリの利用資格を持っていません。ユーザーがアプリをサイドローディングした場合や、アプリを Google Play から取得したのではない場合などが該当します。この問題の解決のために、ユーザーに対して [GET_LICENSED] ダイアログを表示できます。
UNEVALUATED要件が満たされていないため、ライセンスの詳細は評価されませんでした。
次のような原因が考えられます。
- デバイスの信頼性が十分でない。
- デバイスにインストールされているアプリのバージョンが Google Play に認識されていない。
- ユーザーが Google Play にログインしていない。
ユーザーにアプリの利用資格があるかどうかを確かめるには、次のコード スニペットに示すように、appLicensingVerdict が想定どおりであることを確認します。
Kotlin
val accountDetails = JSONObject(payload).getJSONObject("accountDetails") val appLicensingVerdict = accountDetails.getString("appLicensingVerdict") if (appLicensingVerdict == "LICENSED") { // Looks good! }
Java
JSONObject accountDetails = new JSONObject(payload).getJSONObject("accountDetails"); String appLicensingVerdict = accountDetails.getString("appLicensingVerdict"); if (appLicensingVerdict.equals("LICENSED")) { // Looks good! }
環境の詳細フィールド
環境に関する追加のシグナルをオプトインすることもできます。アプリアクセス リスクでは、画面をキャプチャしたり、オーバーレイを表示したり、デバイスを操作したりする可能性のある別のアプリが動作していないかをチェックできます。Play プロテクトの判定結果により、デバイスで Google Play プロテクトが有効になっているか、既知のマルウェアが検出されたかどうかを確認できます。
Google Play Console でアプリアクセス リスクの判定結果または Play プロテクトの判定結果にオプトインしている場合は、API レスポンスに environmentDetails フィールドが含まれます。environmentDetails フィールドには、appAccessRiskVerdict と playProtectVerdict の 2 つの値を含めることができます。
アプリアクセス リスクの判定結果
アカウント アクティビティを有効にすると、environmentDetails フィールドに Play Integrity API
ペイロード の新しいアプリアクセス リスク判定結果が含まれます。
{
"requestDetails": { ... },
"appIntegrity": { ... },
"deviceIntegrity": { ... },
"accountDetails": { ... },
"environmentDetails": {
"appAccessRiskVerdict": {
// This field contains one or more responses, for example the following.
"appsDetected": ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
}
}
}
アプリアクセス リスクが評価された場合、appAccessRiskVerdict には 1 つ以上のレスポンスを含むフィールド appsDetected が含まれます。これらのレスポンスは、検出されたアプリのインストール元に応じて、次の 2 つのグループのいずれかに分類されます。
Play アプリまたはシステムアプリ: Google Play によってインストールされるアプリ、またはデバイスのシステム パーティション(
FLAG_SYSTEMで識別される)にデバイスのメーカーによってプリロードされるアプリ。このようなアプリのレスポンスにはKNOWN_という接頭辞が付きます。その他のアプリ: Google Play からインストールされていないアプリ。デバイスのメーカーによってシステム パーティションにプリロードされたアプリは除外されます。このようなアプリのレスポンスには
UNKNOWN_という接頭辞が付きます。
次のレスポンスが返されることがあります。
KNOWN_INSTALLED、UNKNOWN_INSTALLED- 対応するインストール元と一致するアプリがインストールされています。
KNOWN_CAPTURING、UNKNOWN_CAPTURING- アプリの実行中に画面を表示するために使用できる権限が有効になっているアプリが実行されています。これには、デバイスで実行されている Google Play で認識されている検証済みのユーザー補助サービスは含まれません。
KNOWN_CONTROLLING、UNKNOWN_CONTROLLING- デバイスの制御やアプリへの入力の直接制御、アプリの入出力のキャプチャに使用できる権限が有効になっているアプリがあります。これには、デバイスで実行されている Google Play で認識されている検証済みのユーザー補助サービスは含まれません。
KNOWN_OVERLAYS、UNKNOWN_OVERLAYS- アプリにオーバーレイを表示するために使用できる権限が有効になっているアプリが実行されています。これには、デバイスで実行されている Google Play で認識されている検証済みのユーザー補助サービスは含まれません。
- 空(空の値)
必要な要件が満たされていない場合、アプリアクセス リスクは評価されません。この場合、
appAccessRiskVerdictフィールドは空になります。次のような原因が考えられます。- デバイスの信頼性が十分でない。
- デバイスのフォーム ファクタがスマートフォン、タブレット、折りたたみ式デバイスではない。
- デバイスで Android 6(API レベル 23)以降が実行されていない。
- デバイスにインストールされているアプリのバージョンが Google Play に認識されていない。
- デバイス上の Google Play ストアのバージョンが古い。
- ユーザー アカウントに Play ライセンスがない。
verdictOptOutパラメータを使用して標準リクエストが使用された。- 標準リクエストのアプリアクセス リスクをまだサポートしていない Play Integrity API ライブラリ バージョンで標準リクエストが使用された。
アプリアクセス リスクでは、Google Play のユーザー補助機能に関する高度な審査を経た検証済みのユーザー補助サービスは、(デバイス上のどのアプリストアからインストールされたかに関係なく)自動的に除外されます。「除外」とは、デバイスで実行されている検証済みユーザー補助サービスが、アプリアクセス リスク判定でキャプチャ、制御、オーバーレイのレスポンスを返さないことを意味します。ユーザー補助アプリの Google
Play のユーザー補助機能に関する高度な審査をリクエストするには、アプリのマニフェストで isAccessibilityTool フラグが true に設定されていることを確認して Google
Play に公開するか、審査をリクエストします。
アプリアクセス リスクの判定結果の例
次の表に、アプリアクセス リスクの判定結果の例とその意味を示します(この表は可能な結果をすべて挙げたものではありません)。
| アプリアクセス リスク判定結果のレスポンス例 | 解釈 |
|---|---|
appsDetected:["KNOWN_INSTALLED"]
|
Google Play で認識されているインストール済みアプリ、またはデバイス メーカーによってシステム パーティションにプリロードされているアプリのみがあります。 キャプチャ、制御、オーバーレイの判定結果となるアプリは実行されていません。 |
appsDetected:["KNOWN_INSTALLED","UNKNOWN_INSTALLED","UNKNOWN_CAPTURING"]
|
Google Play によってインストールされたアプリ、またはデバイスのメーカーによってシステム パーティションにプリロードされたアプリがあります。 画面の表示や、他の入出力のキャプチャに使用できる権限が有効になっている実行中の他のアプリがあります。 |
appsDetected:["KNOWN_INSTALLED","KNOWN_CAPTURING","UNKNOWN_INSTALLED","UNKNOWN_CONTROLLING"]
|
画面の表示や、他の入出力のキャプチャに使用できる権限が有効になっている Play アプリまたはシステムアプリが実行されています。 また、デバイスの制御やアプリへの入力の直接制御に使用できる権限が有効になっている実行中の他のアプリがあります。 |
appAccessRiskVerdict: {}
|
要件が満たされていないため、アプリアクセス リスクは評価されませんでした(たとえば、デバイスの信頼性が十分ではなかった場合など)。 |
リスクレベルに応じて、続行できる判定結果の組み合わせと、対処する判定結果を決定できます。次のコード スニペットは、画面をキャプチャしたりアプリを操作したりする可能性のある実行中のアプリがないことを確認する例を示しています。
Kotlin
val environmentDetails = JSONObject(payload).getJSONObject("environmentDetails") val appAccessRiskVerdict = environmentDetails.getJSONObject("appAccessRiskVerdict") if (appAccessRiskVerdict.has("appsDetected")) { val appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString() if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) { // Looks good! } }
Java
JSONObject environmentDetails = new JSONObject(payload).getJSONObject("environmentDetails"); JSONObject appAccessRiskVerdict = environmentDetails.getJSONObject("appAccessRiskVerdict"); if (appAccessRiskVerdict.has("appsDetected")) { String appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString() if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) { // Looks good! } }
アプリアクセス リスクの判定結果を修正する
リスクレベルに応じて、ユーザーがリクエストやアクションを完了する前に、対処するアプリアクセス リスクの判定結果を決定できます。 アプリアクセス リスクの判定結果を確認した後、ユーザーに表示できる Google Play のプロンプト(省略可)があります。CLOSE_UNKNOWN_ACCESS_RISK を表示して、アプリアクセス リスクの判定結果の原因となっている不明なアプリを閉じるようユーザーに求めることも、CLOSE_ALL_ACCESS_RISK を表示して、アプリアクセス リスクの判定結果の原因となっているすべてのアプリ(既知と不明)を閉じるよう ユーザーに求めることもできます。
Play プロテクトの判定結果
この機能を有効にすると、environmentDetails フィールドに Play Integrity API
ペイロード の Play プロテクトの判定結果が含まれるようになります。
"environmentDetails": {
"playProtectVerdict": "NO_ISSUES"
}
playProtectVerdict の値は次のいずれかになります。
NO_ISSUES- Play プロテクトはオンになっていますが、デバイスにおいてアプリの問題は検知されませんでした。
NO_DATA- Play プロテクトはオンになっていますが、まだスキャンが実行されていません。デバイスまたは Play ストア アプリが最近リセットされた可能性があります。
POSSIBLE_RISK- Play プロテクトがオフになっています。
MEDIUM_RISK- Play プロテクトがオンになっており、有害な可能性があるアプリがデバイスにインストールされていることが検知されました。
HIGH_RISK- Play プロテクトがオンになっており、危険なアプリがデバイスにインストールされていることが検知されました。
UNEVALUATEDPlay プロテクトの判定結果は評価されませんでした。
次のような原因が考えられます。
- デバイスの信頼性が十分でない。
- ユーザー アカウントに Play ライセンスがない。
Play プロテクトの判定結果の使用方法に関するガイダンス
アプリのバックエンド サーバーは、リスク許容度に基づいて、判定結果に基づく処理方法を決定できます。推奨される使い方と、考えられるユーザーの操作には次のようなものがあります。
NO_ISSUES- Play プロテクトがオンになっていて、問題は検出されていないため、ユーザーの操作は必要ありません。
POSSIBLE_RISKとNO_DATA- この判定結果を受け取ったら、Play プロテクトがオンになっていてスキャンが実行されているか確認するようユーザーに依頼します。
NO_DATAはまれにしか表示されません。 MEDIUM_RISKとHIGH_RISK- リスク許容度に応じて、Play プロテクトを起動し、Play プロテクトの警告に対応するようユーザーに依頼できます。ユーザーがこれらの要件を満たすことができない場合は、サーバー アクションからブロックできます。