برای جزئیات بیشتر، میتوانید نسخه نمایشی ارائهدهنده ایمیل ساختگی کد را گامبهگام دنبال کنید و به مراحل صادرکننده در API درستیسنجی ایمیل و پیشنهادهای پروتکل درستیسنجی ایمیل مراجعه کنید.
بهعنوان صادرکننده، لازم نیست برای آزمایش مبدأ ثبتنام کنید یا کد ارائه دهید زیرا سایت طرف متکی رفتار مرورگر را راهاندازی میکند. مطمئن شوید که نقطههای پایانی شما برای پاسخ به این درخواستها پیکربندی شدهاند.
پیکربندی کاوش صادرکننده
برای اینکه مرورگرها بتوانند بهطور خودکار نقاط پایانی درستیسنجی شما را هنگام انتخاب نشانی ایمیل متعلق به دامنهتان پیدا کنند، پیکربندیتان را بااستفاده از «ساناد» و نقطه پایانی .well-known پروتکل انتقال ابرمتن نمایان کنید.
پیکربندی گزارش نماینده ساناد
یک ساختار ساناد TXT در دامنه ایمیل خود پیکربندی کنید که اختیار درستیسنجی را به شناسه صادرکننده شما واگذار میکند. این شناسهها میتوانند از همان دامنه استفاده کنند بسته به زیرساخت شما.
قالب ضبط: _email-verification.<email-domain>
فایل منطقه نمونه:
_email-verification.example.com IN TXT "iss=accounts.issuer.example"
میزبانی نقطه پایانی .well-known/email-verification
فایل فراداده JSON را در دامنه صادرکننده خود تحت مسیر /.well-known/ میزبانی کنید.
این فایل قابلیتهای صدور شما و الگوریتمهای امضای رمزنگاریشدهای را که زیرساختتان پشتیبانی میکند مشخص میکند.
نقطه پایانی: 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
ممکن است ازقبل یک منبع .well-known JSON اضافی را بهعنوان بخشی از Federated Credentials (FedCM)
API پیادهسازی کرده باشید. این منبع پیوندهایی به نقطه پایان حسابها و نشانی وب ورود به سیستم شما ارائه میدهد.
نقطه پایانی: 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
یا وضعیت را بااستفاده از جاوا اسکریپت در زمینه برنامه وب خود بهروز کنید:
navigator.login.setStatus("logged-in");
navigator.login.setStatus("logged-out");
رسیدگی به درخواستهای صدور
issuance_endpoint شما درخواست application/json POST را دریافت میکند که
شامل کلید email و سرصفحههای امضاهای پیام HTTP برای Signature،
Signature-Input، و Signature-Key است.
از کتابخانهای استفاده کنید که از سرایندهای ساختاری و «امضاهای پیام 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درخواستی برای درستیسنجی است.
پاسخ صدور
پساز اعتبارسنجی موفقیتآمیز جلسه و نشان درخواست، یک
JWT افشای انتخابی (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-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 نسخه ۱۵۴ و بالاترSec-Fetch-Dest: email-verification(با خط تیره) ارسال میکند، درحالیکه Chrome نسخه ۱۵۳emailverification(بدون خط تیره) ارسال میکرد. هر دو مقدار را درطول عرضه بپذیرید. - عدم تطابق «امضای پیام HTTP» (
@authority) در پشت پروکسی: هنگام درستیسنجی امضای RFC 9421، عنصر@authorityمیزبان عمومی را منعکس میکند. اگر سرورتان پشت یک پروکسی معکوس یا ترازکننده بار قرار دارد، نشانی وب درستیسنجی را بااستفاده ازX-Forwarded-Host(یا مبدأ عمومیتان) بهجای نام میزبان داخلی بازسازی کنید وContent-Digestرا روی بایتهای بدنه درخواست خام قبلاز تجزیه JSON محاسبه کنید.
مرورگر 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: مطمئن شوید ادعایissEVT دقیقاً منشأ HTTPS (https://<issuer-domain>، بدون اسلش انتهایی) مطابق با فراداده.well-known/email-verificationشما باشد، وcnf.jwkکلید عمومی موقت مرورگر را از سرصفحهSignature-Keyجاسازی کند.