WebView-তে ডিজিটাল ক্রেডেনশিয়ালের অনুরোধ করুন

এই নির্দেশিকায় বর্ণনা করা হয়েছে যে WebView ব্যবহার করে এমন Android অ্যাপে ক্রেডেনশিয়াল ম্যানেজার ব্যবহার করে কীভাবে ডিজিটাল ক্রেডেনশিয়ালের জন্য অনুরোধ করতে হয়। ওয়েব পেজ ও অ্যাপের মধ্যে যোগাযোগ সহজ করতে জাভাস্ক্রিপ্ট ব্রিজ ব্যবহার করুন।

এক নজরে

WebView থেকে ডিজিটাল ক্রেডেনশিয়াল অনুরোধের লাইফ সাইকেল সম্পর্কে নিম্নলিখিত ধাপে বর্ণনা করা হয়েছে:

  1. অনুরোধ তৈরি করা: WebView-তে থাকা ওয়েব পেজ অ্যাপ সার্ভারের কাছে অনুরোধ করে, যা OpenID4VP অনুরোধ JSON তৈরি করে এবং তা ফেরত পাঠায়।
  2. অনুরোধ শুরু করা: ওয়েব পেজটি অনুরোধ JSON ব্যবহার করে ডিজিটাল ক্রেডেনশিয়ালের অনুরোধ করতে navigator.credentials.get({ digital: ... }) ব্যবহার করে।
  3. ইন্টারসেপশন: ইনজেক্ট করা bridge.js এই কল ইন্টারসেপ্ট করে, নির্দিষ্ট OpenID4VP অনুরোধ JSON এক্সট্র্যাক্ট করে এবং Android অ্যাপে পাস করে।
  4. Android হ্যান্ডলিং: Android অ্যাপ মেসেজটি রিসিভ করে এবং CredentialManager.getCredential API-কে কল করে।
  5. ব্যবহারকারীর বেছে নেওয়া: ক্রেডেনশিয়াল ম্যানেজার একটি UI দেখায় যা ব্যবহারকারীকে তার ক্রেডেনশিয়াল শেয়ার করার জন্য প্রম্পট করে। Android অ্যাপে ক্রেডেনশিয়াল ফেরত পাঠানো হয়।
  6. ব্রিজ উত্তর: Android অ্যাপ ব্রিজ ব্যবহার করে ওয়েব পেজে উত্তর ফেরত পাঠায়।
  7. সম্পূর্ণ করা: ওয়েব পেজ উত্তর পায় এবং তা ম্যানেজ করে।

পূর্বশর্ত

WebView-তে ডিজিটাল ক্রেডেনশিয়ালের জন্য জাভাস্ক্রিপ্ট ব্রিজ প্রয়োগ করার আগে, আপনার প্রোজেক্ট নিম্নলিখিত প্রয়োজনীয়তা পূরণ করছে কিনা তা নিশ্চিত করুন:

  • Android ভার্সনের সাথে মানানসই: আপনার অ্যাপ Android 6.0 (API লেভেল 23) বা তার পরবর্তী যেকোনও ভার্সনে কাজ করতে হবে।
  • হোস্ট অ্যাপ কন্ট্রোল: আপনাকে অবশ্যই WebView হোস্ট করা Android অ্যাপ কন্ট্রোল করতে হবে যাতে আপনি ওয়েব পেজ লোড করার আগে WebMessageListener অ্যাটাচ করতে পারেন।
  • HTTPS এবং টপ-লেভেল ফ্রেম: ক্রেডেনশিয়ালের অনুরোধ করা ওয়েব পেজটি অবশ্যই https://-এর মাধ্যমে পরিবেশিত হতে হবে এবং মূল ফ্রেমে রান করতে হবে (isMainFrame অবশ্যই true হতে হবে)। সাবফ্রেম এবং এম্বেড করা <iframe> এলিমেন্ট কাজ করে না।
  • পরীক্ষামূলক API চালু করা: Digital Credentials API পরীক্ষামূলক হওয়ায়, আপনাকে অবশ্যই @OptIn(ExperimentalDigitalCredentialApi::class)-এর সাথে GetDigitalCredentialOption ব্যবহার করে এমন ক্লাস বা পদ্ধতি অ্যানোটেট করতে হবে।

ডিপেন্ডেন্সি যোগ করুন

আপনার অ্যাপ মডিউলের build.gradle.kts ফাইলে ক্রেডেনশিয়াল ম্যানেজার এবং AndroidX WebKit ডিপেন্ডেন্সি যোগ করুন:

dependencies {
    // Credential Manager dependencies
    implementation("androidx.credentials:credentials:1.7.0-alpha03")
    implementation("androidx.credentials:credentials-play-services-auth:1.7.0-alpha03")

    // AndroidX WebKit (required for WebMessageListener bridge)
    implementation("androidx.webkit:webkit:1.14.0")
}

WebView-তে ডিজিটাল ক্রেডেনশিয়াল প্রয়োগ করা

ক্রেডেনশিয়াল অনুরোধ করতে এবং bridge.js-এর মাধ্যমে তা ইন্টারসেপ্ট করতে, আপনাকে WebView-তে জাভাস্ক্রিপ্ট যোগ করতে হবে।

জাভাস্ক্রিপ্ট অনুরোধ তৈরি করা

WebView-এ চলা জাভাস্ক্রিপ্ট এবং Android কোডের মধ্যে যোগাযোগ করতে, আপনার WebView-এ জাভাস্ক্রিপ্ট কোড ইনজেক্ট করুন:

// Example digital credential request to request verified email
const request = {
  "providers": [
      {
        "protocol": "openid4vp",
        "request": JSON.stringify({
          "requests": [
            {
              "protocol": "openid4vp-v1-unsigned",
              "data": {
                "response_type": "vp_token",
                "response_mode": "dc_api",
                "nonce": "n-0S6_W_2F", // Generate dynamically
                "dcql_query": {
                  "credentials": [
                    {
                      "id": "user_info_query",
                      "format": "dc+sd-jwt",
                      "meta": {
                        "vct_values": ["UserInfoCredential"]
                      },
                      "claims": [
                        {"path": ["email"]},
                        {"path": ["email_verified"]},
                        {"path": ["name"]}
                      ]
                    }
                  ]
                }
              }
            }
          ]
      })
    }
  ]
};

try {
  const credential = await navigator.credentials.get({
    digital: request
  });

  // Process response
} catch (err) {
  // Handle error
}

জাভাস্ক্রিপ্ট ব্রিজ তৈরি করা

bridge.js নামের একটি ফাইল তৈরি করুন অথবা evaluateJavascript ব্যবহার করে এই কোড ইনজেক্ট করুন। এই স্ক্রিপ্ট অনুরোধ ইন্টারসেপ্ট করতে এবং Android অ্যাপে ইনার OpenID4VP JSON স্ট্রিং পাঠাতে navigator.credentials.get ওভাররাইড করে।

(function() {
  if (!navigator.credentials) {
    navigator.credentials = {};
  }

  const originalGet = navigator.credentials.get;

  // Overrides navigator.credentials.get() to intercept W3C Digital Credential requests.
  navigator.credentials.get = async function(options) {

    if (options && options.digital) {
      if (window.DigitalCredentialBridge) {
        return new Promise((resolve, reject) => {
          const digital = options.digital;

          if (digital.providers && digital.providers.length > 0) {
            const provider = digital.providers[0];

            if (provider.protocol === "openid4vp") {
              const requestJson = provider.request;

              const message = {
                type: "get",
                request: requestJson
              };

              console.log("Sending message to native bridge:", JSON.stringify(message));
              // Send the request string to native Android code
              window.DigitalCredentialBridge.postMessage(JSON.stringify(message));

              // Receive the response sent from native code using replyProxy.postMessage()
              window.DigitalCredentialBridge.onmessage = function(event) {
                console.log("Received response from native bridge:", event.data);
                try {
                  const response = JSON.parse(event.data);
                  if (response.error) {
                    reject(new Error(response.error));
                  } else {
                    resolve(response);
                  }
                } catch (e) {
                  // If it's not JSON, just resolve with the raw data
                  resolve(event.data);
                }
              };
            } else {
              reject(new Error("Unsupported protocol: " + provider.protocol));
            }
          } else {
            reject(new Error("No providers specified in digital credential request"));
          }
        });
      } else {
        console.warn("DigitalCredentialBridge not found, falling back to original");
      }
    }

    if (originalGet) {
      return originalGet.call(navigator.credentials, options);
    } else {
      throw new Error("navigator.credentials.get is not supported and no bridge available");
    }
  };
})();

Android-এ ডিজিটাল ক্রেডেনশিয়াল প্রয়োগ করা

bridge.js থেকে পাঠানো ক্রেডেনশিয়াল সংক্রান্ত অনুরোধ ম্যানেজ করার জন্য আপনার Android অ্যাপ কনফিগার করুন।

Android লিসেনার তৈরি করুন

DigitalCredentialWebListener ক্লাস সেট-আপ করুন যা WebViewCompat.WebMessageListener ইমপ্লিমেন্ট করে। এই ক্লাস JavaScript এবং নেটিভ Android কোডের মধ্যে দ্বিমুখী মেসেজ ম্যানেজ করে, isMainFrame এবং sourceOrigin-এ নিরাপত্তা সংক্রান্ত চেক এনফোর্স করে এবং ওভারল্যাপ করা অনুরোধ প্রতিরোধ করে।

Credential Manager হ্যান্ডলার প্রয়োগ করা

ডিভাইস থেকে ডিজিটাল ক্রেডেনশিয়ালের জন্য অনুরোধ করতে getCredential-এ কল করুন।

@OptIn(ExperimentalDigitalCredentialApi::class)
class CredentialManagerHandler(private val context: Context) {
  private val credentialManager = CredentialManager.create(context)

  suspend fun getDigitalCredential(requestJson: String): String {
    val digitalCredentialOption = GetDigitalCredentialOption(requestJson)
    val getCredRequest = GetCredentialRequest(listOf(digitalCredentialOption))

    return try {
      val result = credentialManager.getCredential(context, getCredRequest)
      val credential = result.credential
      if (credential is DigitalCredential) {
        credential.credentialJson
      } else {
        "{\"error\": \"Unexpected credential type\"}"
      }
    } catch (e: GetCredentialException) {
      "{\"error\": \"${e.message}\"}"
    } catch (e: Exception) {
      "{\"error\": \"Unknown exception\"}"
    }
  }

  companion object {
    private const val TAG = "CredManHandler"
  }
}

আপনার অ্যাক্টিভিটিতে ফ্রেমওয়ার্ক প্রয়োগ করুন

আপনার Activity বা View-এ, WebMessageListener এবং সংশ্লিষ্ট ফাংশন রেজিস্টার করুন।

// Inside your Activity or View setup
AndroidView(
  factory = { context ->
    val handler = CredentialManagerHandler(context)
    WebView(context).apply {
      settings.javaScriptEnabled = true

      // Register the bridge before loading URL
      if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_MESSAGE_LISTENER)) {
                val listener = DigitalCredentialWebListener(coroutineScope, credentialManagerHandler)
                WebViewCompat.addWebMessageListener(
                    webView,
                    INTERFACE_NAME,
                    setOf("*"),
                    listener
                )


      loadUrl("https://your-secure-domain.com/login")
    }
  },
)

ফ্লো পরীক্ষা করা হচ্ছে

WebView এবং Android অ্যাপের মধ্যে যোগাযোগ কনফার্ম করতে ফ্লো পরীক্ষা করুন। প্রসেস চলাকালীন WebView-তে ক্রেডেনশিয়াল সিলেক্টর দেখা যায় এবং প্রসেস সম্পূর্ণ হলে বেছে নেওয়া ক্রেডেনশিয়াল WebView-তে ফিরে আসে।