रिलाइंग पार्टी के लिए लागू करने की सुविधा

अपनी साइट पर ईमेल पते की पुष्टि करने की सुविधा लागू करने के लिए, अपने फ़ॉर्म मार्कअप को अपडेट करें, ताकि टोकन का अनुरोध किया जा सके. साथ ही, आने वाले टोकन के लिए सर्वर-साइड से होने वाली पुष्टि करने की सुविधा जोड़ें.

ओरिजिन ट्रायल के लिए रजिस्टर करना

पुष्टि करने वाली साइटों पर, ओरिजिन ट्रायल कॉन्फ़िगर होना चाहिए.

Chrome 154 और इसके बाद के वर्शन में, तीसरे पक्ष के ऑरिजिन के लिए उपलब्ध कराए गए ट्रायल इस्तेमाल किए जा सकते हैं. हालांकि, इसके लिए एक ज़रूरी शर्त है: ट्रायल के लिए रजिस्टर किया गया ऑरिजिन, जारी करने वाले के ऑरिजिन के जैसा ही होना चाहिए. उदाहरण के लिए:

  • जारी करने वाला डोमेन: issuer.example
  • OT registrant: https://issuer.example
  • JavaScript ऑरिजिन: https://issuer.example (या https://app.issuer.example, जिसमें सबडोमेन मैचिंग की सुविधा होती है)

फ़ॉर्म फ़ील्ड कॉन्फ़िगर करना

ईमेल सबमिट करने वाले फ़ॉर्म में, छिपा हुआ टोकन फ़ील्ड जोड़ें:

<input
  type="email"
  name="email-address"
  autocomplete="email">
<input
  type="hidden"
  name="token"
  autocomplete="email-verification-token"
  nonce="rAnD0m-VaLuE">

फ़ील्ड की ज़रूरी शर्तें:

  • ईमेल फ़ील्ड: type="email" और autocomplete="email" सेट करें, ताकि Chrome पते को ऑटोमैटिक भर सके और उसे पहचान सके.
  • टोकन फ़ील्ड एट्रिब्यूट:
    • autocomplete="email-verification-token" सेट करें: Chrome इस फ़ील्ड की पहचान करता है, ताकि सबमिट करने पर टोकन अपने-आप भर जाए.
    • सेट nonce="<VALUE>": साइट को सेशन से जुड़ा यूनीक नॉनस देना होगा, ताकि फ़ॉर्म सबमिशन की पुष्टि की जा सके.

ईमेल पते की पुष्टि करने वाले टोकन (ईवीटी) की पुष्टि करना

जब उपयोगकर्ता फ़ॉर्म सबमिट करता है, तो आपके सर्वर को ईमेल पता और छिपे हुए फ़ील्ड से टोकन मिलता है. अगर टोकन फ़ील्ड खाली है, तो इसका मतलब है कि ब्राउज़र या सेवा देने वाली कंपनी, ईवीपी के साथ काम नहीं करती है या उपयोगकर्ता ने पुष्टि करने की प्रोसेस छोड़ दी है. अगर ऐसा होता है, तो पुष्टि करने की मौजूदा प्रोसेस पर वापस जाएं. जैसे, ओटीपी या मैजिक लिंक भेजना.

अगर कोई टोकन मौजूद है, तो इस तरह से उसकी पुष्टि करें:

  1. एसडी-जेडब्लूटी लाइब्रेरी का इस्तेमाल करके टोकन को पार्स करें.
  2. अनुमानित वैल्यू और सेशन के दावों की पुष्टि करें.
  3. डीएनएस डेलिगेशन की पुष्टि करें.
  4. जारी करने वाले का मेटाडेटा ढूंढना और JWKS फ़ेच करना.
  5. क्रिप्टोग्राफ़िक सिग्नेचर और कुंजी बाइंडिंग की पुष्टि करें.

1. टोकन पार्स करना

यह टोकन, RFC 9901: Selective Disclosure JWT (SD-JWT+KB) फ़ॉर्मैट का इस्तेमाल करता है. अपने प्लैटफ़ॉर्म के हिसाब से, टोकन को पार्स करने और उसकी पुष्टि करने के लिए सही लाइब्रेरी का इस्तेमाल करें. उदाहरण के लिए, Node के लिए @sd-jwt/core और jose का इस्तेमाल किया जा सकता है. यह इस तरह दिखता है: जारी करने वाले व्यक्ति के हस्ताक्षर वाला JWT, इसके बाद ज़ाहिर की गई जानकारी, और आखिर में कुंजी बाइंडिंग वाला JWT. हर कॉम्पोनेंट को टिल्ड से अलग किया जाता है:

<Issuer-signed EVT>~<Disclosure 1>~...~<Disclosure N>~<Key Binding JWT>

मौजूदा समय में, टोकन में कोई भी डिसक्लोज़र नहीं है (<Issuer-signed EVT>~<Key Binding JWT>). हालांकि, आने वाले समय में इसमें बदलाव हो सकता है.

लाइब्रेरी की मदद से टोकन को डिकोड करें:

import { decodeSdJwtSync } from "@sd-jwt/core";
import { createHash } from "node:crypto";
const hasher = (data, alg) =>
  createHash(alg === "sha-256" ? "sha256" : alg)
    .update(data)
    .digest();
const decoded = decodeSdJwtSync(rawToken, hasher);
const evtPayload = decoded.jwt.payload;
const kbPayload = decoded.kbJwt?.payload;

अगर verifier.example, demo@provider.example की पुष्टि करता है, तो डिकोड किया गया टोकन इस तरह दिखता है:

{
  "evtJwtDecodedHeader": {
    "typ": "evt+jwt",
    "alg": "EdDSA",
    "kid": "issuer-key-id"
  },
  "evtJwtDecodedPayload": {
    "iss": "https://provider.example",
    "iat": 12345678901,
    "exp": 12345679901,
    "cnf": {
      "jwk": {
        "kty": "OKP",
        "crv": "Ed25519",
        "x": "pUbLiCkEy123pUbLiCkEy123pUbLiCkEy123"
      }
    },
    "email": "demo@provider.example",
    "email_verified": true
  },
  "kbJwtDecodedHeader": {
    "alg": "EdDSA",
    "typ": "kb+jwt"
  },
  "kbJwtDecodedPayload": {
    "aud": "https://verifier.example",
    "iat": 12345678901,
    "nonce": "rAnDoM123rAnDoM123rAnDoM123rAnDoM123",
    "sd_hash": "hAsH456hAsH456hAsH456hAsH456hAsH456"
  },
  "disclosures": []
}

2. अनुमानित वैल्यू और सेशन के दावों की पुष्टि करना

देखें कि पेलोड में दी गई बुनियादी वैल्यू, आपकी दी गई और उम्मीद के मुताबिक वैल्यू से मेल खाती हैं या नहीं:

  • email_verified: true होना चाहिए.
  • email: यह फ़ॉर्म में सबमिट किए गए ईमेल पते से मेल खाना चाहिए.
  • aud (ऑडियंस): यह आपकी साइट के ऑरिजिन से मेल खाना चाहिए.
  • nonce: यह आपके फ़ॉर्म में दिए गए नॉनस से मेल खाना चाहिए.
  • iat (जारी करने की तारीख) और exp (समयसीमा खत्म होने की तारीख): पुष्टि करें कि टोकन की समयसीमा खत्म नहीं हुई है और वह मान्य है.

3. डीएनएस डेलिगेशन की पुष्टि करना

ईमेल पते के डोमेन के लिए, _email-verification डीएनएस रिकॉर्ड की पुष्टि करें. उदाहरण के लिए, demo@gmail.com के लिए, _email-verification.gmail.com TXT रिकॉर्ड के लिए क्वेरी करें. इस सेवा देने वाली कंपनी के लिए क्वेरी, खाते की लोकेशन दिखाती है. यह लोकेशन accounts.google.com है.

$ dig +short TXT _email-verification.gmail.com
"iss=accounts.google.com"

पुष्टि करें कि जारी करने वाली कंपनी की स्कीम https:// है और https://<domain>, ईवीटी में मौजूद iss दावे से मेल खाता है.

4. ईवीटी के हस्ताक्षर की पुष्टि करना

https://<issuer>/.well-known/email-verification से, जारी करने वाले के डिस्कवरी मेटाडेटा को फ़ेच करें:

{
  "issuance_endpoint": "https://accounts.google.com/gsi/email-verification/issue",
  "jwks_uri": "https://verifiablecredentials-pa.googleapis.com/.well-known/vc-public-jwks",
  "signing_alg_values_supported": ["EdDSA"]
}

jwks_uri से JSON वेब कुंजी सेट फ़ेच करें.

टोकन पैकेज की पुष्टि करने के लिए, SD-JWT लाइब्रेरी का इस्तेमाल करें. लाइब्रेरी, पुष्टि करने की प्रोसेस को मैनेज करती है:

  1. फ़ेच किए गए JWKS के हिसाब से, EVT पर जारी करने वाले के हस्ताक्षर की पुष्टि की जा रही है.
  2. cnf.jwk में मौजूद कुछ समय के लिए मान्य सार्वजनिक पासकोड का इस्तेमाल करके, KB-JWT पर ब्राउज़र के हस्ताक्षर की पुष्टि करना.
  3. कुंजी बाइंडिंग की पुष्टि करना (aud, nonce, और डाइजेस्ट हैश sd_hash).

Node.js में पुष्टि करने के लॉजिक का उदाहरण:

import { SDJwtInstance } from "@sd-jwt/core";
import { importJWK, compactVerify } from "jose";
import { createHash } from "node:crypto";
const hasher = (data, alg) =>
  createHash(alg === "sha-256" ? "sha256" : alg)
    .update(data)
    .digest();
const sdJwt = new SDJwtInstance({ hasher });
sdJwt.config({
  hasher,
  // Verifier for the Issuer-signed EVT
  verifier: async (data, sig) => {
    const token = `${data}.${sig}`;
    const header = decoded.jwt.header;
    const headerAlg = header.alg || "ES256";
    // Match by kid if present, or iterate across matching algorithm keys
    const keysToTry = header.kid
      ? jwksData.keys.filter(k => k.kid === header.kid)
      : jwksData.keys;
    for (const jwk of keysToTry) {
      try {
        const pubKey = await importJWK(jwk, jwk.alg || headerAlg);
        await compactVerify(token, pubKey);
        return true;
      } catch {
        // Try next candidate key
      }
    }
    return false;
  },
  // Verifier for the Key Binding JWT (KB-JWT)
  kbVerifier: async (data, sig) => {
    try {
      const browserJwkKey = evtPayload.cnf?.jwk;
      if (!browserJwkKey) return false;
      const pubKey = await importJWK(browserJwkKey, decoded.kbJwt.header.alg || "ES256");
      await compactVerify(`${data}.${sig}`, pubKey);
      return true;
    } catch {
      return false;
    }
  },
});
// The library automatically verifies EVT signature, KB-JWT signature, audience, nonce, and sd_hash
const result = await sdJwt.verify(rawToken, {
  kb: {
    expectedNonce: sessionNonce,
    expectedAudience: "https://example.com",
    required: true,
  },
});
const verifiedPayload = result.payload;

सभी चरणों को पूरा करने के बाद, आपने ईमेल सेवा देने वाली कंपनी के ज़रिए अपने ईमेल पते की पुष्टि कर ली है. अगर पुष्टि नहीं हो पाती है, तो उपयोगकर्ता को पुष्टि करने वाला ईमेल भेजें. इसके लिए, सामान्य तरीके का इस्तेमाल करें.

समस्या का हल

अगर पुष्टि नहीं हो पाती है या ब्राउज़र टोकन नहीं देता है, तो यहां दी गई सामान्य समस्याएं देखें:

सबमिट करने पर टोकन फ़ील्ड खाली है

  • ऑरिजिन ट्रायल के लिए रजिस्ट्रेशन: पुष्टि करें कि पेज पर Origin-Trial हेडर या <meta> टैग दिखाया गया हो. तीसरे पक्ष के ऑरिजिन ट्रायल (Chrome 154+) के लिए, रजिस्टर किया गया ट्रायल ऑरिजिन, जारी करने वाले के लिए एक ही साइट का होना चाहिए (https://<issuer-domain>). किसी साइट पर ऑरिजिन ट्रायल कॉन्फ़िगरेशन की जांच करने के लिए, DevTools में ऐप्लिकेशन > फ़्रेम > (ज़रूरी फ़्रेम चुनें) > ऑरिजिन ट्रायल पर जाएं.
  • फ़ॉर्म मार्कअप: <input type="email" autocomplete="email"> और <input type="hidden" autocomplete="email-verification-token" nonce="...">, दोनों एक ही <form> एलिमेंट में होने चाहिए. ये शैडो ड़ॉम बाउंड्री में अलग-अलग नहीं होने चाहिए. साथ ही, nonce खाली नहीं होना चाहिए.
  • जल्दी सबमिट किया गया या फिर से इस्तेमाल किया गया पेज: ईमेल पता डालने या अपने-आप भरने के बाद, ब्राउज़र बैकग्राउंड में टोकन फ़ेच करता है. अनुरोध पूरा होने से पहले सबमिट करने पर, टोकन खाली रह जाता है. ऐसा तब हो सकता है, जब उपयोगकर्ता अपना ईमेल पता डालने के बाद, फ़ॉर्म सबमिट करने के लिए Return दबाता है.
  • ब्राउज़र और सेवा देने वाली कंपनी से जुड़ी ज़रूरी शर्तें: उपयोगकर्ता को उसी ब्राउज़र प्रोफ़ाइल में, सेवा देने वाली कंपनी के साथ साइन इन करना होगा. साथ ही, Chrome की सेटिंग में पुष्टि किया गया ईमेल चालू करना होगा (chrome://settings/contactInfo).

कार्ड जारी करने वाली कंपनी के हस्ताक्षर की पुष्टि नहीं हो सकी

  • kid हेडर मौजूद नहीं है: EVT हेडर और JWKS में kid (कुंजी का आईडी) दावा मौजूद होना ज़रूरी नहीं है. उदाहरण के लिए, Gmail में kid मौजूद नहीं होता है. अगर kid मौजूद नहीं है, तो कुंजी के आईडी को खोजने में गड़बड़ी होने के बजाय, जारी करने वाले के jwks_uri में मौजूद सभी संभावित कुंजियों को दोहराएं.
  • एल्गोरिदम आइडेंटिफ़ायर (EdDSA और Ed25519): जारी करने वाले और लाइब्रेरी, EdDSA या Ed25519 (ES256 के साथ) में से किसी एक को तय कर सकते हैं. पक्का करें कि JWK इंपोर्ट और पुष्टि करने का लॉजिक, दोनों आइडेंटिफ़ायर को स्वीकार करता हो.
  • जारी करने वाले (iss) का ऑरिजिन फ़ॉर्मैट: डीएनएस टीएक्सटी रिकॉर्ड (_email-verification.<domain>) में सिर्फ़ होस्टनेम (iss=accounts.issuer.example) होता है, जबकि ईवीटी iss का दावा पूरा एचटीटीपीएस ऑरिजिन (https://accounts.issuer.example, आखिर में स्लैश नहीं) होता है. तुलना करने से पहले, डीएनएस रिकॉर्ड वैल्यू में https:// प्रीफ़िक्स जोड़ें.

कुंजी बाइंड करने (KB-JWT) की पुष्टि नहीं हो सकी

  • नॉनस का मेल न खाना या उसकी समयसीमा खत्म हो जाना: पक्का करें कि <input> में रेंडर किया गया nonce, आपके सर्वर पर मौजूद चालू सेशन के नॉनस से मेल खाता हो. साथ ही, उसे किसी दूसरे टैब ने बदला न हो या पिछले अनुरोध में इस्तेमाल न किया गया हो.
  • ऑडियंस (aud) का मेल न खाना: aud दावा, पुष्टि करने वाले व्यक्ति के एचटीटीपीएस ऑरिजिन (https://verifier.example, जिसमें कोई पाथ या ट्रेलिंग स्लैश नहीं होता) का होता है.

ईमेल पते के दावे (email) की तुलना नहीं की जा सकी

  • केसिंग और कैननिकल बनाना: Chrome 156+ में, फ़ॉर्म में डाली गई वैल्यू के हिसाब से email दावा दिखाया जाता है. हालांकि, ब्राउज़र के पुराने वर्शन या सेवा देने वाली कंपनियां, कैननिकल पता दिखा सकती हैं. उदाहरण के लिए, first.last@example.com के लिए First.Last@example.com. टोकन के email दावे की तुलना, सबमिट किए गए फ़ॉर्म की वैल्यू से करते समय, केस-इनसेंसिटिव तुलना का इस्तेमाल करें.