ডিজিটাল ক্রেডেনশিয়ালস এপিআই ব্যবহার করে ইমেল যাচাইকরণ বাস্তবায়ন করুন

এই নির্দেশিকায় বর্ণনা করা হয়েছে কিভাবে একটি OpenID for Verifiable Presentations (OpenID4VP) অনুরোধের মাধ্যমে Digital Credentials Verifier API ব্যবহার করে যাচাইকৃত ইমেল পুনরুদ্ধার বাস্তবায়ন করা যায়।

নির্ভরতা যোগ করুন

আপনার অ্যাপের build.gradle ফাইলে Credential Manager-এর জন্য নিম্নলিখিত ডিপেন্ডেন্সিগুলো যোগ করুন:

কোটলিন

dependencies {
    implementation("androidx.credentials:credentials:1.7.0-alpha01")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha01")
}

গ্রোভি

dependencies {
    implementation "androidx.credentials:credentials:1.7.0-alpha01"
    implementation "androidx.credentials:credentials-play-services-auth:1.7.0-alpha01"
}

ক্রেডেনশিয়াল ম্যানেজার শুরু করুন

আপনার অ্যাপ বা অ্যাক্টিভিটি কনটেক্সট ব্যবহার করে একটি CredentialManager অবজেক্ট তৈরি করুন।

// Use your app or activity context to instantiate a client instance of
// CredentialManager.
private val credentialManager = CredentialManager.create(context)

ডিজিটাল পরিচয়পত্রের অনুরোধটি তৈরি করুন

একটি যাচাইকৃত ইমেলের অনুরোধ করতে, একটি GetCredentialRequest তৈরি করুন যাতে একটি GetDigitalCredentialOption অন্তর্ভুক্ত থাকে। এই বিকল্পটির জন্য OpenID for Verifiable Presentations (OpenID4VP) অনুরোধ হিসাবে ফরম্যাট করা একটি requestJson স্ট্রিং প্রয়োজন।

OpenID4VP অনুরোধের JSON-কে অবশ্যই একটি নির্দিষ্ট কাঠামো অনুসরণ করতে হবে। বর্তমান প্রোভাইডারগুলো একটি বাইরের "digital": {"requests": [...]} র‍্যাপারসহ একটি JSON কাঠামো সমর্থন করে।

        val nonce = generateSecureRandomNonce()

// This request follows the OpenID4VP spec
        val openId4vpRequest = """
    {
      "requests": [
        {
          "protocol": "openid4vp-v1-unsigned",
          "data": {
            "response_type": "vp_token",
            "response_mode": "dc_api",
            "nonce": "$nonce",
            "dcql_query": {
              "credentials": [
                {
                  "id": "user_info_query",
                  "format": "dc+sd-jwt",
                   "meta": { 
                      "vct_values": ["UserInfoCredential"] 
                   },
                  "claims": [ 
                    {"path": ["email"]}, 
                    {"path": ["name"]},  
                    {"path": ["given_name"]},
                    {"path": ["family_name"]},
                    {"path": ["picture"]},
                    {"path": ["hd"]},
                    {"path": ["email_verified"]}
                  ]
                }
              ]
            }
          }
        }
      ]
    }
    """

        val getDigitalCredentialOption = GetDigitalCredentialOption(requestJson = openId4vpRequest)
        val request = GetCredentialRequest(listOf(getDigitalCredentialOption))

অনুরোধটিতে নিম্নলিখিত মূল তথ্য রয়েছে:

  • DCQL কোয়েরি : dcql_query ক্রেডেনশিয়াল টাইপ এবং অনুরোধ করা ক্লেইমগুলো ( email_verified ) নির্দিষ্ট করে। ভেরিফিকেশনের স্তর নির্ধারণ করতে আপনি অন্যান্য ক্লেইমের জন্যও অনুরোধ করতে পারেন। কয়েকটি সম্ভাব্য ক্লেইম নিচে দেওয়া হলো:

    • email_verified : রেসপন্সে এটি একটি বুলিয়ান ভ্যালু, যা নির্দেশ করে ইমেলটি ভেরিফাইড কিনা।
    • hd (হোস্টেড ডোমেইন): রেসপন্সে এটি খালি থাকে।
  • যদি ইমেলটি @gmail.com ছাড়া অন্য কোনো ইমেল হয়, তাহলে গুগল অ্যাকাউন্ট তৈরি করার সময় গুগল এই ইমেলটি যাচাই করে, কিন্তু এর কোনো ফ্রেশনেস ক্লেইম থাকে না। তাই, গুগল-বহির্ভূত ইমেলের ক্ষেত্রে, ব্যবহারকারীকে যাচাই করার জন্য আপনার একটি অতিরিক্ত যাচাই প্রক্রিয়া, যেমন একটি OTP, বিবেচনা করা উচিত। ক্রেডেনশিয়ালের স্কিমা এবং email_verified এর মতো ফিল্ড যাচাই করার নির্দিষ্ট নিয়মগুলো বোঝার জন্য, গুগল আইডেন্টিটি গাইড দেখুন।

  • ননস (nonce) : প্রতিটি অনুরোধের জন্য একটি অনন্য, ক্রিপ্টোগ্রাফিকভাবে সুরক্ষিত র‍্যান্ডম মান তৈরি করা হয়। এটি নিরাপত্তার জন্য অত্যন্ত গুরুত্বপূর্ণ, কারণ এটি রিপ্লে অ্যাটাক প্রতিরোধ করে।

  • UserInfoCredential : এই মানটি এক বিশেষ ধরনের ডিজিটাল পরিচয়পত্রকে বোঝায়, যাতে ব্যবহারকারীর বৈশিষ্ট্য থাকে। ইমেইল যাচাইকরণের ব্যবহার ক্ষেত্রটিকে আলাদাভাবে চিহ্নিত করার জন্য অনুরোধে এটি অন্তর্ভুক্ত করা অত্যন্ত গুরুত্বপূর্ণ।

এরপরে, openId4vpRequest JSON-টিকে একটি GetDigitalCredentialOption মধ্যে রাখুন, একটি GetCredentialRequest তৈরি করুন এবং getCredential() কল করুন।

ব্যবহারকারীর কাছে অনুরোধটি উপস্থাপন করুন

ক্রেডেনশিয়াল ম্যানেজার বিল্ট-ইন UI ব্যবহার করে ব্যবহারকারীর কাছে অনুরোধটি উপস্থাপন করুন।

try {
    // Requesting Digital Credential from user...
    val result = credentialManager.getCredential(activity, request)

    when (val credential = result.credential) {
        is DigitalCredential -> {
            val responseJsonString = credential.credentialJson

            // Successfully received digital credential response.

            // Next, parse this response and send it to your server.
            // ...
        }

        else -> {
            // handle Unexpected State() - Up to the developer
        }
    }
} catch (e: Exception) {
    // handle exceptions - Up to the developer
}

ক্লায়েন্টের প্রতিক্রিয়াটি পার্স করুন

প্রতিক্রিয়া পাওয়ার পর, আপনি ক্লায়েন্টে একটি প্রাথমিক পার্সিং করতে পারেন। এটি UI তাৎক্ষণিকভাবে আপডেট করার জন্য উপযোগী, যেমন—ব্যবহারকারীর নাম দেখানো।

নিম্নলিখিত কোডটি র' সিলেক্টিভ ডিসক্লোজার JWT (SD-JWT) নিষ্কাশন করে এবং একটি হেল্পার ব্যবহার করে এর ক্লেইমগুলো ডিকোড করে।

// 1. Parse the outer JSON wrapper to get the `vp_token`
val responseData = JSONObject(responseJsonString)
val vpToken = responseData.getJSONObject("vp_token")

// 2. Extract the raw SD-JWT string
val credentialId = vpToken.keys().next()
val rawSdJwt = vpToken.getJSONArray(credentialId).getString(0)

// 3. Use your parser to get the verified claims
// Server-side validation/parsing is highly recommended.

// Assumes a local parser like the one in our SdJwtParser.kt sample
val claims = SdJwtParser.parse(rawSdJwt)
Log.d("TAG", "Parsed Claims: ${claims.toString(2)}")

// 4. Create your VerifiedUserInfo object with REAL data
val userInfo = VerifiedUserInfo(
    email = claims.getString("email"),
    displayName = claims.optString("name", claims.getString("email"))
)

প্রতিক্রিয়াটি সামলান।

ক্রেডেনশিয়াল ম্যানেজার এপিআই একটি DigitalCredential প্রতিক্রিয়া ফেরত দেবে।

নিচে মূল responseJsonString দেখতে কেমন হয় এবং ভেতরের SD-JWT পার্স করার পর ক্লেইমগুলো কেমন দেখায় তার একটি উদাহরণ দেওয়া হলো, যেখানে যাচাইকৃত ইমেলের পাশাপাশি অতিরিক্ত মেটাডেটাও পাওয়া যায়:

/*
// Example of the raw JSON response from credential.credentialJson:
{
  "vp_token": {
    // This key matches the 'id' you set in your dcql_query
    "user_info_query": [
      // The SD-JWT string (Issuer JWT ~ Disclosures ~ Key Binding JWT)
      "eyJhbGciOiJ...~WyI...IiwgImVtYWlsIiwgInVzZXJAZXhhbXBsZS5jb20iXQ~...~eyJhbGciOiJ..."
    ]
  }
}

// Example of the parsed and verified claims from the SD-JWT on your server:
{
  "cnf": {
    "jwk": {..}
  },
  "exp": 1775688222,
  "iat": 1775083422,
  "iss": "https://verifiablecredentials-pa.googleapis.com",
  "vct": "UserInfoCredential",
  "email": "jane.doe.246745@gmail.com",
  "email_verified": true,
  "given_name": "Jane",
  "family_name": "Doe",
  "name": "Jane Doe",
  "picture": "http://example.com/janedoe/me.jpg",
  "hd": ""
}
 */

অ্যাকাউন্ট তৈরির জন্য সার্ভার-সাইড যাচাইকরণ

যেহেতু প্রাপ্ত ইমেলটি ক্রিপ্টোগ্রাফিকভাবে যাচাই করা হয়, তাই আপনি ইমেল OTP যাচাইকরণ ধাপটি বাদ দিতে পারেন, যা সাইন-আপের জটিলতা উল্লেখযোগ্যভাবে কমিয়ে দেয় এবং সম্ভাব্যভাবে রূপান্তর বৃদ্ধি করে। এই প্রক্রিয়াটি আপনার সার্ভারে পরিচালনা করাই সবচেয়ে ভালো। ক্লায়েন্ট কাঁচা প্রতিক্রিয়া ( vp_token সহ) এবং আসল nonce একটি নতুন সার্ভার এন্ডপয়েন্টে পাঠায়।

যাচাইকরণের জন্য, অ্যাকাউন্ট তৈরি করার বা ব্যবহারকারীকে লগ ইন করানোর আগে আপনার অ্যাপ্লিকেশনকে অবশ্যই ক্রিপ্টোগ্রাফিক বৈধতার জন্য সম্পূর্ণ responseJsonString আপনার সার্ভারে পাঠাতে হবে।

ডিজিটাল পরিচয়পত্রটি আপনার সার্ভারের জন্য দুই স্তরের গুরুত্বপূর্ণ যাচাইকরণ প্রদান করে:

  • ডেটার সত্যতা : ইস্যুকারী ( iss ) URL এবং SD-JWT স্বাক্ষর যাচাই করার মাধ্যমে প্রমাণিত হয় যে, কোনো বিশ্বস্ত কর্তৃপক্ষ এই ডেটা ইস্যু করেছে।
  • উপস্থাপকের পরিচয় : cnf ফিল্ড এবং কী বাইন্ডিং ( kb ) সিগনেচার যাচাই করার মাধ্যমে নিশ্চিত হওয়া যায় যে, ক্রেডেনশিয়ালটি মূলত যে ডিভাইসের জন্য ইস্যু করা হয়েছিল, সেই ডিভাইসেই শেয়ার করা হচ্ছে। এর ফলে এটি অন্য কোনো ডিভাইসে ইন্টারসেপ্ট বা ব্যবহার হওয়া থেকে সুরক্ষিত থাকে।

সার্ভারে যাচাইকরণ প্রক্রিয়ায় নিম্নলিখিত বিষয়গুলো অবশ্যই পূরণ করতে হবে:

  • ইস্যুকারী যাচাই করুন : নিশ্চিত করুন যে iss (ইস্যুকারী) ফিল্ডটি https://verifiablecredentials-pa.googleapis.com সাথে মেলে।
  • স্বাক্ষর যাচাই করুন : https://verifiablecredentials-pa.googleapis.com/.well-known/vc-public-jwks-এ উপলব্ধ পাবলিক কী (JWK) ব্যবহার করে SD-JWT-এর স্বাক্ষর পরীক্ষা করুন।

সম্পূর্ণ নিরাপত্তার জন্য, রিপ্লে অ্যাটাক প্রতিরোধ করতে nonce টিও যাচাই করে নিন।

এই ধাপগুলো একত্রিত করার মাধ্যমে, আপনার সার্ভার নতুন অ্যাকাউন্টটি চালু করার আগে ডেটার সত্যতা এবং উপস্থাপকের পরিচয় উভয়ই যাচাই করতে পারে, যা নিশ্চিত করে যে ক্রেডেনশিয়ালটি হস্তগত বা নকল করা হয়নি।

try {
    // Send the raw credential response and the original nonce to your server.
    // Your server must validate the response. createAccountWithVerifiedCredentials
    // is a custom implementation per each RP for server side verification and account creation.
    val serverResponse = createAccountWithVerifiedCredentials(responseJsonString, nonce)

    // Server returns the new account info (e.g., email, name)
    val claims = JSONObject(serverResponse.json)

    val userInfo = VerifiedUserInfo(
        email = claims.getString("email"),
        displayName = claims.optString("name", claims.getString("email"))
    )

    // handle response - Up to the developer
} catch (e: Exception) {
    // handle exceptions - Up to the developer
}

পাসকি তৈরি

একটি অ্যাকাউন্ট তৈরি করার পর একটি ঐচ্ছিক কিন্তু অত্যন্ত সুপারিশকৃত পরবর্তী পদক্ষেপ হলো অবিলম্বে সেই অ্যাকাউন্টের জন্য একটি পাসকি তৈরি করা । এটি ব্যবহারকারীকে সাইন ইন করার জন্য একটি নিরাপদ, পাসওয়ার্ডবিহীন পদ্ধতি প্রদান করে। এই প্রক্রিয়াটি একটি সাধারণ পাসকি নিবন্ধনের মতোই।

ওয়েবভিউ সমর্থন

একটি WebView-তে ফ্লোটি কার্যকর করার জন্য, ডেভেলপারদের হ্যান্ডঅফ সহজ করতে একটি জাভাস্ক্রিপ্ট ব্রিজ (JS Bridge) প্রয়োগ করা উচিত। এই ব্রিজটি Webview-কে নেটিভ অ্যাপে সংকেত পাঠাতে সাহায্য করে, যার ফলে নেটিভ অ্যাপটি ক্রেডেনশিয়াল ম্যানেজার এপিআই-তে প্রকৃত কলটি করতে পারে।

আরও দেখুন