আরও বিস্তারিত জানতে, আপনি মক ইমেল পরিষেবা প্রদানকারী ডেমো কোড দেখে নিতে পারেন এবং ইমেল যাচাইকরণ এপিআই ও ইমেল যাচাইকরণ প্রোটোকল প্রস্তাবে উল্লিখিত ইস্যুকারী ধাপগুলি দেখতে পারেন।
ইস্যুকারী হিসেবে, আপনাকে অরিজিন ট্রায়ালে সাইন-আপ করতে হবে না বা টোকেন প্রদান করতে হবে না কারণ নির্ভরকারী পার্টি সাইট ব্রাউজারের আচরণ ট্রিগার করে। আপনার এন্ডপয়েন্ট সেইসব অনুরোধের উত্তর দেওয়ার জন্য কনফিগার করা আছে কিনা তা নিশ্চিত করুন।
ইস্যুকারী শনাক্তকরণ কনফিগার করা
আপনার ডোমেনের কোনও ইমেল আইডি বেছে নেওয়া হলে, ব্রাউজারকে অটোমেটিক আপনার যাচাইকরণ এন্ডপয়েন্ট খুঁজে পাওয়ার অনুমতি দিতে, DNS ও .well-known HTTP এন্ডপয়েন্ট ব্যবহার করে আপনার কনফিগারেশন
এক্সপোজ করুন।
ডিএনএস ডেলিগেট রেকর্ড কনফিগার করা
আপনার ইমেল ডোমেনে একটি DNS TXT রেকর্ড কনফিগার করুন যা আপনার ইস্যুকারী শনাক্তকারীকে যাচাইকরণ কর্তৃত্ব প্রদান করে। আপনার পরিকাঠামোর উপর নির্ভর করে এইসব শনাক্তকারী একই ডোমেন ব্যবহার করতে পারে।
রেকর্ড ফর্ম্যাট: _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 রিসোর্স প্রয়োগ করেছেন। এই রিসোর্স আপনার অ্যাকাউন্টের এন্ডপয়েন্ট এবং লগ-ইন URL-এর
লিঙ্ক প্রদান করে।
এন্ডপয়েন্ট: https://<domain>/.well-known/web-identity
উত্তরের উদাহরণ:
{
"accounts_endpoint": "https://accounts.issuer.example/accounts",
"login_url": "https://accounts.issuer.example/login"
}
অ্যাকাউন্ট এন্ডপয়েন্ট ব্যবহার করা
FedCM API-এর অ্যাকাউন্ট এন্ডপয়েন্ট বর্তমানে সাইন-ইন করা অ্যাকাউন্টের একটি তালিকা প্রদান করে। নিচে দেওয়া উদাহরণে ন্যূনতম উত্তর দেখানো হয়েছে। আরও বিবরণের জন্য, পরিচয় প্রদানকারী প্রয়োগ করা সংক্রান্ত নির্দেশিকা দেখুন।
এন্ডপয়েন্ট: .well-known/web-identity-এ উল্লেখ করা হয়েছে
নিচে একটি উদাহরণ উত্তর দেওয়া হল:
{
"accounts": [
{
"id": "demo-example",
"name": "Demo User",
"email": "demo@example.com",
"given_name": "Demo"
}
]
}
Login Status API-এর সাথে ইন্টিগ্রেট করা
প্রোভাইডারের সাথে ব্যবহারকারীর একটি অ্যাক্টিভ সেশন থাকতে হবে এবং আপনাকে Login Status API ব্যবহার করে ব্রাউজারকে সেই বিষয়ে সিগন্যাল দিতে হবে।
ব্যবহারকারী সফলভাবে সাইন-ইন বা সাইন-আউট করলে, ম্যাচ করা HTTP উত্তর হেডার পরিবেশন করুন:
Set-Login: logged-in
Set-Login: logged-out
অথবা, আপনার ওয়েব অ্যাপ্লিকেশন কন্টেক্সটে JavaScript ব্যবহার করে স্ট্যাটাস আপডেট করুন:
navigator.login.setStatus("logged-in");
navigator.login.setStatus("logged-out");
ইস্যু করার অনুরোধ ম্যানেজ করা
আপনার issuance_endpoint একটি application/json POST অনুরোধ পায় যাতে
Signature, Signature-Input ও Signature-Key-এর জন্য email কী ও HTTP মেসেজ
সিগনেচার হেডার থাকে।
আপনার এনভায়রনমেন্টের জন্য স্ট্রাকচার্ড হেডার ও HTTP মেসেজ সিগনেচার কাজ করে এমন লাইব্রেরি
ব্যবহার করুন। 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-এ সেট করা আছে।- HTTP মেসেজ সিগনেচার:
Signature-Key-এ থাকা ক্ষণস্থায়ী পাবলিক কী ব্যবহার করে অনুরোধের সিগনেচার যাচাই করুন এবংContent-Digestভ্যালিডেট করুন। - পেলোড: JSON বডিতে
emailযাচাইকরণের জন্য অনুরোধ করা স্ট্রিং থাকে।
ইস্যু সংক্রান্ত উত্তর
সেশন ও অনুরোধ টোকেন সফলভাবে যাচাই করার পরে, আপনার প্ল্যাটফর্মের জন্য উপযুক্ত লাইব্রেরি ব্যবহার করে JSON হিসেবে ফেরত
দেওয়া একটি সাইন করা
সিলেক্টিভ ডিসক্লোজার JWT (SD-JWT) তৈরি করুন। যেমন, 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-inHTTP হেডার সেট করে বাnavigator.login.setStatus("logged-in")কল করে কিনা তা নিশ্চিত করুন। - সেশন কুকি ব্লক করা হয়েছে (
SameSite=None): ব্রাউজার আপনারaccounts_endpointওissuance_endpointকোনও আলাদা সাইটে কোনও নির্ভরযোগ্য পার্টি থেকে সংগ্রহ করে। যেহেতু এগুলি ক্রস-সাইট অনুরোধ, তাই আপনার সেশন কুকিতেSameSite=None; Secureথাকতেই হবে।SameSite=Laxকুকি একই সাইটের যাচাইকারীকে দিয়ে পরীক্ষা করার সময় কাজ করে, কিন্তু ক্রস-সাইট অনুরোধের ক্ষেত্রে এটি বাদ দেওয়া হয়। - ডিসকভারি বা অ্যাকাউন্ট না মেলা: যাচাই করে দেখুন যে
_email-verification.<email-domain>একটি TXT রেকর্ড রিটার্ন করে (iss=<issuer-domain>,https://ছাড়া), দুটি.well-knownএন্ডপয়েন্টইContent-Type: application/jsonরিটার্ন করে এবংaccounts_endpointউত্তরে এমন একটি অ্যাকাউন্ট আছে যারemail, লেখা ঠিকানার সাথে মেলে।
ইস্যু করার অনুরোধ যাচাইকরণ সম্পূর্ণ হয়নি
Sec-Fetch-Destহেডার বানান: Chrome 154+Sec-Fetch-Dest: email-verification(হাইফেন সহ) পাঠায়, যেখানে Chrome 153emailverification(হাইফেন ছাড়া) পাঠায়। রোল-আউটের সময় দুটি ভ্যালুই গ্রহণ করা হবে।- প্রক্সির পিছনে HTTP মেসেজ সিগনেচার (
@authority) না মেলা: RFC 9421 সিগনেচার যাচাই করার সময়,@authorityকম্পোনেন্টটি সর্বজনীন হোস্টকে প্রতিফলিত করে। আপনার সার্ভার যদি কোনও রিভার্স প্রক্সি বা লোড ব্যালেন্সারের পিছনে থাকে, তাহলে ইন্টার্নাল হোস্টনেমের পরিবর্তেX-Forwarded-Host(বা আপনার পাবলিক অরিজিন) ব্যবহার করে যাচাইকরণ URL রিকনস্ট্রাক্ট করুন এবং JSON পার্সিংয়ের আগে কাঁচা অনুরোধের বডির বাইটContent-Digestগণনা করুন।
ব্রাউজার রিটার্ন করা issuance_token প্রত্যাখ্যান করে
- পরিবর্তিত বা ক্যাননিক্যাল
emailদাবি: Chrome 156 থেকে, ব্রাউজার চেক করে যে EVTemailদাবিটি অনুরোধ করাemailবাইটের সাথে বাইট-ফর-বাইট ম্যাচ করছে কিনা। আপনার ব্যাকএন্ড যদি কোনও ক্যাননিকাল অ্যাকাউন্ট ফর্ম্যাটে (যেমন,first.LAST@example.comঅনুরোধ করা হলেFirst.Last@example.comরিটার্ন করা) ঠিকানাটি স্বাভাবিক করে তোলে, তাহলে Chrome টোকেনটি বাদ দেয়। ব্যবহারকারীর অ্যাকাউন্টের সাথে অনুরোধটি ম্যাচ করাও, কিন্তু অনুরোধের বডিতে পাওয়া হুবহুemailস্ট্রিংটি ফেরত দিও। - শেষের দিকে টিল্ড (
~) নেই: কোনও ডিসক্লোজার না থাকলেও,issuance_tokenঅবশ্যই একটি বৈধ SD-JWT হতে হবে যার শেষে টিল্ড (<Issuer-signed-JWT>~) থাকবে, যাতে ব্রাউজার<KB-JWT>যোগ করতে পারে। - ম্যাচ না করা
issবাcnf.jwk: EVTissদাবিটি যেন আপনার.well-known/email-verificationমেটাডেটার সাথে হুবহু মিলে যায়, এটি নিশ্চিত করুন। এটি যেন সঠিক HTTPS অরিজিন (https://<issuer-domain>, শেষে কোনও স্ল্যাশ নেই) হয় এবংcnf.jwkযেনSignature-Keyহেডার থেকে ব্রাউজারের ক্ষণস্থায়ী পাবলিক কী এম্বেড করে।