ইন্টিগ্রিটি সংক্রান্ত সিদ্ধান্ত

এই পৃষ্ঠায়, ফিরে আসা ইন্টিগ্রিটি ভার্ডিক্ট কীভাবে ব্যাখ্যা ও ব্যবহার করতে হয় তা বর্ণনা করা হয়েছে। আপনি স্ট্যান্ডার্ড বা ক্লাসিক API অনুরোধ করুন না কেন, একই ধরনের কন্টেন্ট সহ একই ফর্ম্যাটে ইন্টিগ্রিটি ভার্ডিক্ট ফেরত দেওয়া হয়। ইন্টিগ্রিটি ভারডিক্ট ডিভাইস, অ্যাপ ও অ্যাকাউন্টের বৈধতা সংক্রান্ত তথ্য জানায়। আপনার অ্যাপের সার্ভার ডিক্রিপ্ট করা, যাচাই করা ফলাফলের পে-লোড ব্যবহার করে এটি নির্ধারণ করতে পারে যে আপনার অ্যাপে কোনও নির্দিষ্ট অ্যাকশন বা অনুরোধের সাথে কীভাবে সবচেয়ে ভালভাবে এগিয়ে যেতে হবে।

ফিরে আসা ইন্টিগ্রিটি ফলাফল ফর্ম্যাট

পেলোড হল প্লেন-টেক্সট JSON এবং এতে ডেভেলপার-প্রদত্ত তথ্যের পাশাপাশি ইন্টিগ্রিটি সিগন্যাল থাকে।

সাধারণ পে-লোড স্ট্রাকচার নিচে দেওয়া হল:

{
  "requestDetails": { ... },
  "accountDetails": { ... },
  "appIntegrity": { ... },
  "deviceIntegrity": { ... },
  "environmentDetails": { ... }
}

JSON পেলোডে ফিল্ডের ক্রমের ব্যাপারে কোনও গ্যারান্টি দেওয়া হয় না। প্রতিটি অখণ্ডতা সংক্রান্ত সিদ্ধান্ত চেক করার আগে, আপনাকে প্রথমে 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"
}

এইসব ভ্যালু মূল অনুরোধের ভ্যালুর সাথে ম্যাচ করতে হবে। তাই, JSON পেলোডের requestDetails অংশটি যাচাই করে নিন, এটি নিশ্চিত করুন যে requestPackageName এবং requestHash মূল অনুরোধে যা পাঠানো হয়েছিল তার সাথে মিলছে, যেমনটি নিম্নলিখিত কোড স্নিপেটে দেখানো হয়েছে:

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.
        ...
}

জাভা

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"
}

এইসব ভ্যালু মূল অনুরোধের ভ্যালুর সাথে ম্যাচ করতে হবে। তাই, JSON পেলোডের requestDetails অংশটি যাচাই করে নিন, যাতে requestPackageName এবং nonce মূল অনুরোধে পাঠানো তথ্যের সাথে মেলে। এটি নিচের কোড স্নিপেটে দেখানো হয়েছে:

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.
        ...
}

জাভা

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.
        ...
}

অ্যাকাউন্টের বিবরণ ফিল্ড

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!
}

জাভা

JSONObject accountDetails =
    new JSONObject(payload).getJSONObject("accountDetails");
String appLicensingVerdict = accountDetails.getString("appLicensingVerdict");

if (appLicensingVerdict.equals("LICENSED")) {
    // Looks good!
}

অ্যাপ্লিকেশন ইন্টিগ্রিটি ফিল্ড

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!
}

জাভা

JSONObject appIntegrity =
    new JSONObject(payload).getJSONObject("appIntegrity");
String appRecognitionVerdict =
    appIntegrity.getString("appRecognitionVerdict");

if (appRecognitionVerdict.equals("PLAY_RECOGNIZED")) {
    // Looks good!
}

এছাড়াও, আপনি অ্যাপ প্যাকেজের নাম, অ্যাপের ভার্সন ও অ্যাপ সার্টিফিকেট ম্যানুয়ালি চেক করতে পারবেন।

ডিভাইস ইন্টিগ্রিটি ফিল্ড

deviceIntegrity ফিল্ডে একটি ভ্যালু থাকতে পারে, deviceRecognitionVerdict, যার মধ্যে এক বা একাধিক লেবেল থাকে যা দেখায় যে কোনও ডিভাইস কতটা ভালভাবে অ্যাপ ইন্টিগ্রিটি এনফোর্স করতে পারে। কোনও ডিভাইস কোনও লেবেলের মাপকাঠি পূরণ না করলে, 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 হুকিং) বা সিস্টেমের সাথে আপস করার (যেমন, রুট করা) লক্ষণ দেখা যাচ্ছে অথবা অ্যাপটি কোনও ফিজিক্যাল ডিভাইসে চলছে না (যেমন, এমন এমুলেটর যা 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!
}

জাভা

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 ইনস্টল করা আছে কিনা তা নিশ্চিত করুন (যেমন, ডিভাইস রিসেট করার মাধ্যমে) এবং বুটলোডার লক করা আছে কিনা তা নিশ্চিত করুন। এছাড়াও, আপনি 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 ভার্ডিক্টের জন্য MEETS_DEVICE_INTEGRITY এবং ডিভাইসের সব পার্টিশনের জন্য গত এক বছরে নিরাপত্তা আপডেট প্রয়োজন, এর মধ্যে Android OS পার্টিশন প্যাচ ও ভেন্ডর পার্টিশন প্যাচ অন্তর্ভুক্ত।
  • Android 12 ও তার আগের ভার্সনে, MEETS_STRONG_INTEGRITY ভারডিক্ট শুধুমাত্র বুট ইন্টিগ্রিটির হার্ডওয়্যার-ব্যাকড প্রমাণ চায় এবং ডিভাইসে সাম্প্রতিক নিরাপত্তা আপডেট থাকতে হবে, এমন কোনও প্রয়োজন নেই। তাই, MEETS_STRONG_INTEGRITY ব্যবহার করার সময়, deviceAttributes ফিল্ডে Android SDK ভার্সনও বিবেচনা করে দেখার জন্য সাজেস্ট করা হয়।

লেবেলের প্রতিটি শর্ত পূরণ হলে, একটি ডিভাইস, ডিভাইস ইন্টিগ্রিটি সিদ্ধান্তে একাধিক ডিভাইস লেবেল রিটার্ন করবে।

ডিভাইস অ্যাট্রিবিউট

এছাড়াও, আপনি ডিভাইস অ্যাট্রিবিউট চালু করতে পারেন, যা ডিভাইসে চলমান 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.
}

ডিভাইসে সাম্প্রতিক অ্যাক্টিভিটি

এছাড়াও, আপনি সাম্প্রতিক ডিভাইস অ্যাক্টিভিটি চালু করতে পারেন, এটি আপনাকে জানাবে যে গত এক ঘণ্টায় আপনার অ্যাপ কতবার কোনও নির্দিষ্ট ডিভাইসে ইন্টিগ্রিটি টোকেনের অনুরোধ করেছে। অপ্রত্যাশিত, অতিসক্রিয় ডিভাইস থেকে আপনার অ্যাপকে সুরক্ষিত রাখতে, আপনি সাম্প্রতিক ডিভাইস অ্যাক্টিভিটি ব্যবহার করতে পারেন। এটি কোনও অ্যাক্টিভ অ্যাটাকের ইঙ্গিত হতে পারে। আপনি সিদ্ধান্ত নিতে পারেন যে প্রতিটি সাম্প্রতিক ডিভাইস অ্যাক্টিভিটি লেভেলকে কতটা বিশ্বাস করবেন, এটি নির্ভর করে যে আপনি কতবার আশা করেন যে একটি সাধারণ ডিভাইসে ইনস্টল করা আপনার অ্যাপ প্রতি ঘন্টায় একটি ইন্টিগ্রিটি টোকেন অনুরোধ করবে।

আপনি recentDeviceActivity deviceIntegrity ফিল্ডে দুটি ভ্যালু পাওয়ার বিকল্প বেছে নিলে:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "recentDeviceActivity": {
    // "LEVEL_2" is one of several possible values.
    "deviceActivityLevel": "LEVEL_2"
  }
}

deviceActivityLevel-এর সংজ্ঞা মোড অনুযায়ী আলাদা হয় এবং এর নিম্নলিখিত ভ্যালুগুলির মধ্যে একটি থাকতে পারে:

ডিভাইসের সাম্প্রতিক অ্যাক্টিভিটি লেভেল এই ডিভাইসে স্ট্যান্ডার্ড API ইন্টিগ্রিটি টোকেন অনুরোধ প্রতি অ্যাপের জন্য গত এক ঘণ্টায় এই ডিভাইসে ক্লাসিক API ইন্টিগ্রিটি টোকেন অনুরোধ প্রতি অ্যাপের জন্য গত এক ঘণ্টায়
LEVEL_1 (সবচেয়ে কম) 10টি বা স্বল্পতর ৫টি বা তার কম
LEVEL_2 ১১ থেকে ২৫-এর মধ্যে ৬ থেকে ১০টির মধ্যে
LEVEL_3 ২৬ থেকে ৫০ ১১ থেকে ১৫
LEVEL_4 (সর্বোচ্চ) ৫০টির বেশি ১৫টির বেশি
UNEVALUATED সাম্প্রতিক ডিভাইস অ্যাক্টিভিটি মূল্যায়ন করা হয়নি। এটি হতে পারে কারণ:
  • ডিভাইসটি যথেষ্ট বিশ্বাসযোগ্য নয়।
  • ডিভাইসে ইনস্টল করা আপনার অ্যাপের ভার্সন Google Play-এর অজানা।
  • অনুরোধকারী অ্যাপ লাইসেন্সপ্রাপ্ত নয় (Android 13 ও তার পরবর্তী যেকোনও ভার্সনে)।
  • ডিভাইসে প্রযুক্তিগত সমস্যা।

ডিভাইস রিকল (বিটা)

এছাড়াও, আপনি ডিভাইস রিকল বিকল্প বেছে নিতে পারেন, এটি আপনাকে কিছু কাস্টম, প্রতি-ডিভাইস ডেটা নির্দিষ্ট ডিভাইসের সাথে স্টোর করতে দেয় যা আপনি নির্ভরযোগ্যভাবে পুনরুদ্ধার করতে পারবেন যখন আপনার অ্যাপটি পরে একই ডিভাইসে আবার ইনস্টল করা হয়। ইন্টিগ্রিটি টোকেনের অনুরোধ করার পরে, আপনি নির্দিষ্ট ডিভাইসের জন্য ডিভাইস রিকল ভ্যালু পরিবর্তন করতে আলাদা সার্ভার-টু-সার্ভার কল করেন।

আপনি 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 দুটি ফিল্ডে ভাগ করা হয়েছে:

  • values: এই ডিভাইসের জন্য আগে সেট করা বিট ভ্যালু রিকল করুন।
  • writeDates: UTC-তে বিট লেখার তারিখগুলি বছর ও মাস অনুযায়ী সঠিকভাবে মনে রাখুন। কোনও রিকল বিটের লেখার তারিখ প্রতিবার বিটটি true হিসেবে সেট করা হলে আপডেট করা হবে এবং বিটটি false হিসেবে সেট করা হলে সরিয়ে দেওয়া হবে।

ডিভাইস রিকল সংক্রান্ত তথ্য উপলভ্য না থাকলে, ডিভাইস রিকল ভ্যালু খালি থাকবে:

"deviceIntegrity": {
  "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
  "deviceRecall": {
    "values": {},
    "writeDates": {}
  }
}

পরিবেশের বিবরণ ফিল্ড

এছাড়াও, আপনি পরিবেশ সম্পর্কিত অতিরিক্ত সিগন্যাল পাওয়ার বিকল্প বেছে নিতে পারেন। অ্যাপ অ্যাক্সেস ঝুঁকি, স্ক্রিন ক্যাপচার, ওভারলে ডিসপ্লে বা ডিভাইস কন্ট্রোল করার জন্য ব্যবহার করা যেতে পারে এমন অন্য কোনও অ্যাপ চলছে কিনা তা আপনার অ্যাপকে জানায়। Play Protect মতামত থেকে আপনি জানতে পারবেন যে ডিভাইসে Google Play Protect চালু আছে কিনা এবং এটি পরিচিত ম্যালওয়্যার খুঁজে পেয়েছে কিনা।

আপনি যদি নিজের Google Play Console-এ অ্যাপ অ্যাক্সেস ঝুঁকি সংক্রান্ত সিদ্ধান্ত বা Play Protect সংক্রান্ত সিদ্ধান্ত নেওয়ার বিকল্প বেছে নিয়ে থাকেন, তাহলে আপনার API রেসপন্সে environmentDetails ফিল্ড অন্তর্ভুক্ত থাকবে। environmentDetails ফিল্ডে দুটি ভ্যালু, appAccessRiskVerdict ও playProtectVerdict থাকতে পারে।

অ্যাপ অ্যাক্সেস সংক্রান্ত ঝুঁকির ব্যাপারে দেওয়া সিদ্ধান্ত

চালু করা হয়ে গেলে, Play Integrity API পে-লোড-এর মধ্যে থাকা environmentDetails ফিল্ডে নতুন অ্যাপ অ্যাক্সেস সংক্রান্ত ঝুঁকির ফলাফল থাকবে।

{
  "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-এ একটি বা একাধিক উত্তর সহ ফিল্ড থাকে appsDetected। শনাক্ত করা অ্যাপের ইনস্টল সোর্সের উপর নির্ভর করে, এইসব উত্তরকে নিচে উল্লেখ করা দুটি গ্রুপের মধ্যে একটিতে রাখা হয়:

  • 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 Store-এর যে ভার্সন আছে সেটি পুরনো হয়ে গেছে।
  • ব্যবহারকারীর অ্যাকাউন্টে Play লাইসেন্স নেই।
  • verdictOptOut প্যারামিটার সহ একটি স্ট্যান্ডার্ড অনুরোধ ব্যবহার করা হয়েছে।
  • Play Integrity API লাইব্রেরি ভার্সন সহ একটি স্ট্যান্ডার্ড অনুরোধ ব্যবহার করা হয়েছে যা এখনও স্ট্যান্ডার্ড অনুরোধের জন্য অ্যাপ অ্যাক্সেস সংক্রান্ত ঝুঁকিকে সমর্থন করে না।

অ্যাপ অ্যাক্সেস সংক্রান্ত ঝুঁকি অটোমেটিক যাচাই করা অ্যাক্সেসিবিলিটি পরিষেবা বাদ দেয় যেগুলি উন্নত Google Play অ্যাক্সেসিবিলিটি পর্যালোচনার (ডিভাইসে যেকোনও অ্যাপ স্টোর দ্বারা ইনস্টল করা) মাধ্যমে গেছে। "বাদ দেওয়া" কথাটির অর্থ হল, ডিভাইসে চালু থাকা যাচাই করা অ্যাক্সেসিবিলিটি পরিষেবা, অ্যাপ অ্যাক্সেস সংক্রান্ত ঝুঁকির ব্যাপারে দেওয়া সিদ্ধান্তে কোনও ক্যাপচার করা, কন্ট্রোল করা বা ওভারলে সংক্রান্ত উত্তর দেবে না। আপনার অ্যাক্সেসিবিলিটি অ্যাপের জন্য উন্নত Google Play অ্যাক্সেসিবিলিটি রিভিউয়ের অনুরোধ করতে, Google Play-তে এটি প্রকাশ করুন এবং নিশ্চিত করুন যে আপনার অ্যাপের ম্যানিফেস্টে isAccessibilityTool ফ্ল্যাগ 'true' হিসেবে সেট করা আছে অথবা রিভিউয়ের অনুরোধ করুন।

অ্যাপ অ্যাক্সেস রিস্ক সংক্রান্ত ফলাফলের উদাহরণ

নিচের সারণীতে অ্যাপ অ্যাক্সেস সংক্রান্ত ঝুঁকির ব্যাপারে দেওয়া কিছু সিদ্ধান্তের উদাহরণ এবং সেগুলির অর্থ দেওয়া হল (এই সারণীতে সম্ভাব্য সব ফলাফল তালিকাভুক্ত করা হয়নি):

অ্যাপ অ্যাক্সেস সংক্রান্ত ঝুঁকির ব্যাপারে দেওয়া ফলাফলের উত্তরের উদাহরণ ব্যাখ্যা
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!
    }
}

জাভা

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 Protect-এর রায়

চালু করা হয়ে গেলে, Play Integrity API পে-লোড-এর মধ্যে থাকা environmentDetails ফিল্ডে Play Protect সংক্রান্ত ফলাফল থাকবে:

"environmentDetails": {
  "playProtectVerdict": "NO_ISSUES"
}

playProtectVerdict-এর নিম্নলিখিত মানগুলির মধ্যে একটি থাকতে পারে:

NO_ISSUES
Play Protect চালু আছে এবং ডিভাইসে কোনও অ্যাপ সংক্রান্ত সমস্যা খুঁজে পায়নি।
NO_DATA
Play Protect চালু করা আছে কিন্তু এখনও কোনও স্ক্যান করা হয়নি। ডিভাইস বা Play Store অ্যাপ সম্প্রতি রিসেট করা হয়ে থাকতে পারে।
POSSIBLE_RISK
Play Protect বন্ধ করা আছে।
MEDIUM_RISK
Play Protect চালু আছে এবং ডিভাইসে ইনস্টল করা সম্ভাব্য ক্ষতিকর অ্যাপ খুঁজে পেয়েছে।
HIGH_RISK
Play Protect চালু আছে এবং ডিভাইসে ইনস্টল করা বিপজ্জনক অ্যাপ খুঁজে পেয়েছে।
UNEVALUATED

Play Protect-এর সিদ্ধান্ত মূল্যায়ন করা হয়নি।

নিম্নলিখিত কারণ সহ আরও অনেক কারণে এটি হতে পারে:

  • ডিভাইসটি যথেষ্ট বিশ্বাসযোগ্য নয়।
  • ব্যবহারকারীর অ্যাকাউন্টে Play লাইসেন্স নেই।

Play Protect ভারডিক্ট ব্যবহার করা সংক্রান্ত নির্দেশিকা

আপনার অ্যাপের ব্যাকএন্ড সার্ভার, আপনার ঝুঁকি নেওয়ার ক্ষমতা অনুযায়ী ফলাফলের ভিত্তিতে কীভাবে কাজ করবে তা নির্ধারণ করতে পারে। এখানে কিছু সাজেশন ও সম্ভাব্য ব্যবহারকারীর অ্যাকশন দেওয়া হল:

NO_ISSUES
Play Protect চালু আছে এবং কোনও সমস্যা খুঁজে পায়নি, তাই ব্যবহারকারীকে কোনও অ্যাকশন নিতে হবে না।
POSSIBLE_RISK ও NO_DATA
এইসব ভার্ডিক্ট পাওয়ার সময়, ব্যবহারকারীকে Play Protect চালু আছে কিনা এবং স্ক্যান করা হয়েছে কিনা তা চেক করতে বলুন। NO_DATA শুধুমাত্র বিরল পরিস্থিতিতেই দেখানো উচিত।
MEDIUM_RISK ও HIGH_RISK
ঝুঁকি সহ্য করার ক্ষমতার উপর নির্ভর করে, আপনি ব্যবহারকারীকে Play Protect চালু করতে এবং Play Protect-এর সতর্কতা অনুযায়ী ব্যবস্থা নিতে বলতে পারেন। ব্যবহারকারী এইসব প্রয়োজনীয়তা পূরণ করতে না পারলে, আপনি তাকে সার্ভার অ্যাকশন থেকে ব্লক করতে পারেন।