ईमेल सेवा देने वाली कंपनी (जारी करने वाली) के लिए, इस सुविधा को लागू करना

ज़्यादा जानकारी के लिए, नकली ईमेल पते की पुष्टि करने वाली सेवा का डेमो कोड देखें. साथ ही, Email Verification API और Email Verification Protocol के सुझावों में, ईमेल पते की पुष्टि करने वाले के लिए दिए गए चरण देखें.

कार्ड जारी करने वाली कंपनी के तौर पर, आपको ऑरिजिन ट्रायल के लिए साइन अप करने या टोकन देने की ज़रूरत नहीं है. ऐसा इसलिए, क्योंकि भरोसा करने वाली पार्टी की साइट, ब्राउज़र के व्यवहार को ट्रिगर करती है. पक्का करें कि आपके एंडपॉइंट, उन अनुरोधों का जवाब देने के लिए कॉन्फ़िगर किए गए हों.

कार्ड जारी करने वाली कंपनी को खोजने की सुविधा कॉन्फ़िगर करना

जब आपके डोमेन से जुड़ा कोई ईमेल पता चुना जाता है, तब ब्राउज़र को पुष्टि करने वाले आपके एंडपॉइंट अपने-आप ढूंढने की अनुमति देने के लिए, डीएनएस और .well-known एचटीटीपी एंडपॉइंट का इस्तेमाल करके अपना कॉन्फ़िगरेशन दिखाएं.

डीएनएस डेलिगेट रिकॉर्ड कॉन्फ़िगर करना

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

रिकॉर्ड फ़ॉर्मैट: _email-verification.<email-domain>

ज़ोन फ़ाइल का उदाहरण:

_email-verification.example.com IN TXT "iss=accounts.issuer.example"

.well-known/email-verification एंडपॉइंट होस्ट करना

अपने जारीकर्ता डोमेन पर, /.well-known/ पाथ के तहत JSON मेटाडेटा फ़ाइल होस्ट करें. इस फ़ाइल में, कार्ड जारी करने की आपकी क्षमताओं और आपके बुनियादी ढांचे के साथ काम करने वाले क्रिप्टोग्राफ़िक हस्ताक्षर एल्गोरिदम के बारे में बताया गया है.

एंडपॉइंट: https://<issuer-domain>/.well-known/email-verification

जवाब का उदाहरण:

{
  "issuance_endpoint": "https://accounts.issuer.example/email-verification/issuance",
  "jwks_uri": "https://accounts.issuer.example/.well-known/vc-public-jwks",
  "signing_alg_values_supported": ["EdDSA", "ES256"]
}

.well-known/web-identity एंडपॉइंट होस्ट करना

ऐसा हो सकता है कि आपने Federated Credentials (FedCM) API के हिस्से के तौर पर, पहले से ही कोई अतिरिक्त .well-known JSON संसाधन लागू किया हो. इस संसाधन में, आपके खातों के एंडपॉइंट और लॉगिन यूआरएल के लिंक दिए गए हैं.

एंडपॉइंट: https://<domain>/.well-known/web-identity

जवाब का उदाहरण:

{
  "accounts_endpoint": "https://accounts.issuer.example/accounts",
  "login_url": "https://accounts.issuer.example/login"
}

खातों के एंडपॉइंट का इस्तेमाल करना

FedCM API का accounts एंडपॉइंट, फ़िलहाल साइन इन किए गए खातों की सूची दिखाता है. यहां कम से कम जानकारी वाले जवाब का उदाहरण दिया गया है. ज़्यादा जानकारी के लिए, पहचान की पुष्टि करने वाली सेवा को लागू करने से जुड़ी गाइड देखें.

एंडपॉइंट: .well-known/web-identity में बताया गया है

यहां जवाब का एक उदाहरण दिया गया है:

{
  "accounts": [
    {
      "id": "demo-example",
      "name": "Demo User",
      "email": "demo@example.com",
      "given_name": "Demo"
    }
  ]
}

Login Status API के साथ इंटिग्रेट करना

उपयोगकर्ता का सेशन, सेवा देने वाली कंपनी के साथ चालू होना चाहिए. साथ ही, आपको Login Status API का इस्तेमाल करके, ब्राउज़र को यह जानकारी देनी होगी.

जब कोई उपयोगकर्ता साइन इन या साइन आउट कर लेता है, तो उससे मिलता-जुलता एचटीटीपी रिस्पॉन्स हेडर दिखाएं:

Set-Login: logged-in
Set-Login: logged-out

इसके अलावा, अपने वेब ऐप्लिकेशन के कॉन्टेक्स्ट में JavaScript का इस्तेमाल करके स्टेटस अपडेट करें:

navigator.login.setStatus("logged-in");
navigator.login.setStatus("logged-out");

सर्टिफ़िकेट जारी करने के अनुरोधों को मैनेज करना

आपके issuance_endpoint को application/json POST अनुरोध मिलता है. इसमें email कुंजी और Signature, Signature-Input, और Signature-Key के लिए एचटीटीपी मैसेज सिग्नेचर हेडर शामिल होते हैं.

अपने एनवायरमेंट के लिए, ऐसी लाइब्रेरी का इस्तेमाल करें जो स्ट्रक्चर्ड हेडर और एचटीटीपी मैसेज सिग्नेचर के साथ काम करती हो. Node.js में, structured-headers और http-message-sig का इस्तेमाल किया जा सकता है.

अनुरोध का पूरा फ़ॉर्मैट:

POST /email-verification/issuance HTTP/1.1
Host: provider.example
Accept: application/json
Content-Digest: sha-256=:aBc123aBc123aBc123aBc123aBc123=:
Content-Type: application/json
Sec-Fetch-Dest: email-verification
Signature: sig=:+dEf567dEf567/dEf567dEf567dEf567/dEf567==:
Signature-Input: sig=("@method" "@authority" "@path" "content-digest" "signature-key");created=1786455840
Signature-Key: sig=hwk;crv="Ed25519";kty="OKP";x="gHi890_gHi890_gHi890"

{email: "demo@example.com"}

अनुरोध को पार्स करें और उसकी पुष्टि करें:

  • सत्र की पुष्टि करना: अनुरोध के साथ भेजी गई, पहले पक्ष की सेशन कुकी की पुष्टि करें. उपयोगकर्ता की पुष्टि होना ज़रूरी है.
  • Sec-Fetch-Dest हेडर: इसे email-verification पर सेट करें.
  • एचटीटीपी मैसेज सिग्नेचर: Signature-Key में मौजूद एफ़ेमरल पब्लिक की का इस्तेमाल करके, अनुरोध के सिग्नेचर की पुष्टि करें. साथ ही, Content-Digest की पुष्टि करें.
  • पेलोड: JSON बॉडी में, पुष्टि के लिए अनुरोध की गई email स्ट्रिंग शामिल होती है.

पासपोर्ट जारी करने से जुड़ा जवाब

सेशन और अनुरोध टोकन की पुष्टि हो जाने के बाद, हस्ताक्षर किया गया SD-JWT जनरेट करें. इसे JSON के तौर पर दिखाया जाता है. इसके लिए, अपने प्लैटफ़ॉर्म के हिसाब से सही लाइब्रेरी का इस्तेमाल करें. उदाहरण के लिए, Node के लिए @sd-jwt/core और jose का इस्तेमाल किया जा सकता है.

रॉ पेलोड का फ़ॉर्मैट कुछ ऐसा दिखना चाहिए:

{
  "iss": "https://accounts.issuer.example",
  "iat": 1780272000,
  "exp": 1780272300,
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "pUbLiCKeY123pUbLiCKeY123pUbLiCKeY123",
      "y": "pUbLiCKeY456pUbLiCKeY456pUbLiCKeY456"
    }
  },
  "email": "demo@example.com",
  "email_verified": true
}

टोकन बनाएं, उस पर हस्ताक्षर करें, और उसे वापस भेजें:

import { importJWK, CompactSign } from "jose";
import { SDJwtInstance } from "@sd-jwt/core";
import crypto from "node:crypto";
// Issuer private key from secure storage
const privateKey = await importJWK(PRIVATE_KEY_JWK, "EdDSA");
const origin = url.origin;
const currentTime = Math.floor(Date.now() / 1000);
const evtPayload = {
  iss: origin,
  iat: currentTime,
  exp: currentTime + 300, // 5 minutes
  cnf: {
    jwk: browserJwk,
  },
  email: payload.email, // exactly as received in payload
  email_verified: true,
};
const sdJwt = new SDJwtInstance({
  signer: async (data) => {
    const [headerB64, payloadB64] = data.split(".");
    const header = JSON.parse(Buffer.from(headerB64, "base64url").toString());
    const payload = Buffer.from(payloadB64, "base64url");
    const signed = await new CompactSign(payload).setProtectedHeader(header).sign(privateKey);
    return signed.split(".").pop()!;
  },
  signAlg: "EdDSA",
  hasher: async (data, alg) => {
    const nodeAlg = alg.replace("-", "");
    return new Uint8Array(crypto.createHash(nodeAlg).update(data).digest());
  },
  hashAlg: "sha-256",
  saltGenerator: async () => crypto.randomBytes(16).toString("base64url"),
});
const issuanceToken = await sdJwt.issue(evtPayload, undefined, {
  header: {
    alg: "EdDSA",
    kid: PRIVATE_KEY_JWK.kid,
    typ: "evt+jwt",
  },
});
return sendResponse({ issuance_token: issuanceToken, }, 200);

नतीजे के तौर पर मिलने वाला जवाब कुछ ऐसा दिखता है:

{
  "issuance_token": "tOkEn123tOkEn123tOkEn123...~"
}

ईमेल पते की पुष्टि करने वाला टोकन बनाने और उस पर हस्ताक्षर करने के बाद, ब्राउज़र इसे पुष्टि करने वाली साइट को भेजता है.

समस्या का हल

अगर ब्राउज़र आपके एंडपॉइंट से संपर्क नहीं करता है या जारी किए गए टोकन अस्वीकार करता है, तो इन सामान्य समस्याओं की जांच करें:

ब्राउज़र, accounts_endpoint या issuance_endpoint को कभी कॉल नहीं करता

  • लॉगिन की स्थिति सेट नहीं है: Chrome सिर्फ़ तब आपके एंडपॉइंट से क्वेरी करता है, जब उसे पता हो कि उपयोगकर्ता ने साइन इन किया है. पक्का करें कि साइन इन करने की प्रोसेस के दौरान, Set-Login: logged-in एचटीटीपी हेडर सेट किया गया हो या navigator.login.setStatus("logged-in") को कॉल किया गया हो.
  • सेशन कुकी ब्लॉक की गई हैं (SameSite=None): ब्राउज़र, किसी दूसरी साइट पर भरोसा करने वाले पक्ष से आपकी accounts_endpoint और issuance_endpoint फ़ेच करता है. ये अनुरोध दूसरी साइट से किए गए हैं. इसलिए, आपकी सेशन कुकी में SameSite=None; Secure शामिल होना चाहिए. SameSite=Lax कुकी, एक ही साइट पर पुष्टि करने वाले व्यक्ति के लिए काम करती है. हालांकि, इसे दूसरी साइट से किए गए अनुरोधों में शामिल नहीं किया जाता.
  • डिस्कवरी या खाते का मेल न खाना: पुष्टि करें कि _email-verification.<email-domain> एक टीएक्सटी रिकॉर्ड (iss=<issuer-domain>, https:// के बिना) दिखाता है, दोनों .well-known एंडपॉइंट Content-Type: application/json दिखाते हैं, और accounts_endpoint के जवाब में ऐसा खाता शामिल है जिसका email, डाले गए पते से मेल खाता है.

सर्टिफ़िकेट जारी करने के अनुरोध की पुष्टि नहीं हो सकी

  • Sec-Fetch-Dest हेडर की स्पेलिंग: Chrome 154 और इसके बाद के वर्शन में Sec-Fetch-Dest: email-verification (हाइफ़न के साथ) भेजा जाता है, जबकि Chrome 153 में emailverification (हाइफ़न के बिना) भेजा जाता था. रोलआउट के दौरान, दोनों वैल्यू स्वीकार करें.
  • प्रॉक्सी के पीछे मौजूद एचटीटीपी मैसेज सिग्नेचर (@authority) का मेल न खाना: आरएफ़सी 9421 सिग्नेचर की पुष्टि करते समय, @authority कॉम्पोनेंट, सार्वजनिक तौर पर उपलब्ध होस्ट को दिखाता है. अगर आपका सर्वर रिवर्स प्रॉक्सी या लोड बैलेंसर के पीछे है, तो पुष्टि करने वाले यूआरएल को फिर से बनाएं. इसके लिए, इंटरनल होस्टनेम के बजाय X-Forwarded-Host (या आपका सार्वजनिक ऑरिजिन) का इस्तेमाल करें. साथ ही, JSON पार्सिंग से पहले, अनुरोध के मुख्य हिस्से के रॉ बाइट पर Content-Digest का हिसाब लगाएं.

ब्राउज़र, दिखाए गए issuance_token को अस्वीकार करता है

  • बदला गया या कैननिकल किया गया email दावा: Chrome 156 से, ब्राउज़र यह जांच करता है कि EVT email दावा, अनुरोध किए गए email से बाइट-फ़ॉर-बाइट मेल खाता है या नहीं. अगर आपका बैकएंड, पते को कैननिकल खाते के फ़ॉर्मैट में बदलता है (जैसे कि first.LAST@example.com का अनुरोध किए जाने पर First.Last@example.com को वापस भेजना), तो Chrome टोकन को हटा देता है. अनुरोध को उपयोगकर्ता के खाते से मैच करें. हालांकि, अनुरोध के मुख्य हिस्से में मिली email स्ट्रिंग को ही दिखाएं.
  • आखिर में टिल्ड (~) मौजूद नहीं है: भले ही, कोई भी जानकारी ज़ाहिर न की गई हो, issuance_token एक मान्य एसडी-जेडब्ल्यूटी होना चाहिए. इसके आखिर में टिल्ड (<Issuer-signed-JWT>~) होना चाहिए, ताकि ब्राउज़र <KB-JWT> जोड़ सके.
  • iss या cnf.jwk का मेल न खाना: पक्का करें कि EVT iss का दावा, आपके .well-known/email-verification मेटाडेटा से मेल खाने वाला सटीक एचटीटीपीएस ऑरिजिन (https://<issuer-domain>, आखिर में कोई स्लैश नहीं) हो. साथ ही, cnf.jwk, Signature-Key हेडर से ब्राउज़र के कुछ समय के लिए इस्तेमाल होने वाले सार्वजनिक पासकोड को एम्बेड करता हो.