Sitenizde e-posta doğrulamayı uygulamak için form işaretlemenizi güncelleyerek jeton isteyin ve gelen jetonlar için sunucu tarafı doğrulama ekleyin.
Kaynak denemesine kaydolma
Doğrulanan sitelerde, sitelerinde kaynak denemesi yapılandırılmış olmalıdır.
Chrome 154'ten itibaren üçüncü taraf kaynaklı denemeler, önemli bir uyarı ile desteklenir: Deneme için kayıtlı kaynak, verenle aynı site olmalıdır. Örneğin:
- Kart sağlayıcı alanı:
issuer.example - OT kayıtlı kullanıcısı:
https://issuer.example - JavaScript kaynağı:
https://issuer.example(veyahttps://app.issuer.examplealt alan eşleşmesiyle)
Form alanlarını yapılandırma
E-posta gönderme formunuza gizli bir jeton alanı ekleyin:
<input
type="email"
name="email-address"
autocomplete="email">
<input
type="hidden"
name="token"
autocomplete="email-verification-token"
nonce="rAnD0m-VaLuE">
Alan koşulları:
- E-posta alanı: Chrome'un adresi otomatik doldurabilmesi ve tanıyabilmesi için
type="email"veautocomplete="email"değerlerini ayarlayın. - Jeton alanı özellikleri:
- Set
autocomplete="email-verification-token": Chrome, gönderim sırasında jetonu doldurmak için bu alanı tanımlar. nonce="<VALUE>"ayarlanmalıdır: Site, form gönderimini doğrulamak için oturuma bağlı benzersiz bir nonce sağlamalıdır.
- Set
E-posta doğrulama jetonunu (EVT) doğrulayın
Kullanıcı formu gönderdiğinde sunucunuz, e-posta adresini ve gizli alandaki jetonu alır. Boş bir jeton alanı, tarayıcının veya sağlayıcının EVP'yi desteklemediğini ya da kullanıcının doğrulamayı atladığını gösterir. Bu durum ortaya çıkarsa tek kullanımlık şifre veya sihirli bağlantı gönderme gibi mevcut doğrulama sürecinize geri dönün.
Jeton varsa aşağıdaki şekilde doğrulayın:
- SD-JWT kitaplığı kullanarak jetonu ayrıştırın.
- Beklenen değerleri ve oturum taleplerini doğrulayın.
- DNS temsilini doğrulayın.
- Düzenleyen meta verilerini keşfedin ve JWKS'yi getirin.
- Kriptografik imzaları ve anahtar bağlamayı doğrulayın.
1. Jetonu ayrıştırma
Jeton, RFC 9901: Selective Disclosure JWT
(SD-JWT+KB) biçimini kullanır. Jetonu ayrıştırmak ve doğrulamak için platformunuza uygun kitaplıkları kullanın.
Örneğin, Node için @sd-jwt/core ve jose kullanabilirsiniz. Bu, ham biçiminde şu şekilde görünür: Düzenleyen tarafından imzalanmış bir JWT, ardından sıfır veya daha fazla Açıklama ve her bileşeni tilde ile ayrılmış bir Anahtar Bağlama JWT'si ile sona erer:
<Issuer-signed EVT>~<Disclosure 1>~...~<Disclosure N>~<Key Binding JWT>
Mevcut uygulamada jeton sıfır açıklama içerir (<Issuer-signed EVT>~<Key Binding JWT>). Ancak bu durum gelecekte değişebilir.
Kitaplıkla jetonun kodunu çözün:
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 öğesini doğruluyorsa kodu çözülmüş jeton aşağıdaki gibi görünür:
{
"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. Beklenen değerleri ve oturum taleplerini doğrulama
Yükteki temel değerlerin sağladığınız ve beklediğiniz değerlerle eşleştiğini kontrol edin:
email_verified:trueolmalıdır.email: Formda gönderilen e-posta adresiyle eşleşmelidir.aud(kitle): Sitenizin kaynağıyla eşleşmelidir.nonce: Formunuzda sağlanan nonce ile eşleşmelidir.iat(verildiği zaman) veexp(geçerlilik bitişi): Jetonun geçerli zaman aralığında olduğunu ve süresinin dolmadığını onaylayın.
3. DNS temsilini doğrulama
E-posta adresi alanının _email-verification DNS kaydını doğrulayın. Örneğin, demo@gmail.com için _email-verification.gmail.com TXT kaydını sorgulayın. Bu sağlayıcı için sorgu, hesap sağlayıcının konumunu (accounts.google.com) döndürür.
$ dig +short TXT _email-verification.gmail.com
"iss=accounts.google.com"
Düzenleyen şemasının https:// olduğunu ve https://<domain> değerinin EVT'deki iss talebiyle eşleştiğini doğrulayın.
4. EVT imzasını doğrulama
Düzenleyenin keşif meta verilerini https://<issuer>/.well-known/email-verification adresinden getirin:
{
"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"]
}
JSON Web Anahtarı Kümesi'ni jwks_uri adresinden getirin.
Jeton paketini doğrulamak için SD-JWT kitaplığınızı kullanın. Kitaplık, doğrulama işlemini koordine eder:
- EVT'deki veren imzasını getirilen JWKS'ye göre doğrulama.
cnf.jwkiçindeki kısa ömürlü ortak anahtarı kullanarak KB-JWT'deki tarayıcı imzasını doğrulama.- Anahtar bağlama (
aud,nonceve özet karmasısd_hash) doğrulanıyor.
Node.js'deki örnek doğrulama mantığı:
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;
Tüm adımlar başarılı olursa e-posta adresini sağlayıcıya karşı doğrulamış olursunuz. Doğrulama başarısız olursa normal akışınızı kullanarak kullanıcıya onay e-postası göndermeye geri dönün.
Sorun giderme
Doğrulama başarısız olursa veya tarayıcı jeton sağlamazsa aşağıdaki yaygın sorunları kontrol edin:
Gönderim sırasında jeton alanı boş
- Kaynak denemesi kaydı:
Origin-Trialbaşlığının veya<meta>etiketinin sayfada yayınlandığını onaylayın. Üçüncü taraf kaynak denemeleri (Chrome 154 ve sonraki sürümler) için kayıtlı deneme kaynağı, verenle aynı site olmalıdır (https://<issuer-domain>). Bir sitedeki kaynak denemesi yapılandırmasını Geliştirici Araçları'nda Uygulama > Çerçeveler > (ilgili çerçeveyi seçin) > Kaynak denemeleri bölümünde inceleyebilirsiniz. - Form işaretlemesi: Hem
<input type="email" autocomplete="email">hem de<input type="hidden" autocomplete="email-verification-token" nonce="...">aynı<form>öğesinde olmalıdır (Shadow DOM sınırları arasında yalıtılmamış) venonceboş olmamalıdır. - Erken gönderim veya yeniden kullanılan sayfa: Tarayıcı, e-posta girildikten veya otomatik olarak doldurulduktan sonra jetonu arka planda getirir. İstek tamamlanmadan gönderilen jeton boş kalır. Bu durum, kullanıcının e-posta adresini girdikten sonra formu göndermek için Enter tuşuna basması halinde yaşanabilir.
- Tarayıcı ve sağlayıcı ön koşulları: Kullanıcı, aynı tarayıcı profilinde katılımcı bir sağlayıcıda oturum açmış olmalı ve Chrome ayarlarında (
chrome://settings/contactInfo) Doğrulanmış E-posta etkin olmalıdır.
Kartı veren kuruluşun imzası doğrulanamıyor
kidüstbilgisi eksik: EVT üstbilgisindeki ve JWKS'dekikid(Anahtar Kimliği) talebi isteğe bağlıdır (örneğin, Gmailkid'ı atlar).kidyoksa anahtar kimliği araması başarısız olmak yerine, veren kuruluşunjwks_uri'sındaki tüm aday anahtarlar arasında yineleme yapın.- Algoritma tanımlayıcıları (EdDSA ve Ed25519): Düzenleyenler ve kitaplıklar
EdDSAveyaEd25519'ü (ES256ile birlikte) belirtebilir. JWK içe aktarma ve doğrulama mantığınızın her iki tanımlayıcıyı da kabul ettiğinden emin olun. - Veren (
iss) kaynak biçimi: DNS TXT kaydı (_email-verification.<domain>) çıplak bir ana makine adı (iss=accounts.issuer.example) içerirken EVTisstalebi tam bir HTTPS kaynağıdır (https://accounts.issuer.example, sonunda eğik çizgi yoktur). Karşılaştırmadan önce DNS kaydı değerinehttps://önekini ekleyin.
Anahtar bağlama (KB-JWT) doğrulaması başarısız oluyor
- Eşleşmeyen veya süresi dolmuş nonce:
<input>içinde oluşturulannonceöğesinin, sunucunuzdaki etkin oturum nonce'uyla eşleştiğinden ve başka bir sekme tarafından üzerine yazılmadığından ya da önceki bir istek tarafından tüketilmediğinden emin olun. - Kitle (
aud) eşleşmemesi:audtalebi, doğrulayıcının HTTPS kaynağıdır (https://verifier.example, yol veya sondaki eğik çizgi olmadan).
E-posta talebi (email) karşılaştırması başarısız oluyor
- Büyük/küçük harf kullanımı ve standartlaştırma: Chrome 156 ve sonraki sürümlerde
emailtalebi, formda girildiği gibi bayt bayt döndürülür. Ancak daha eski tarayıcı sürümleri veya sağlayıcılar, standartlaştırılmış bir adres (örneğin,first.last@example.comiçinFirst.Last@example.com) döndürebilir. Jetonunemailtalebini gönderilen form değeriyle eşleştirirken büyük/küçük harfe duyarlı olmayan bir karşılaştırma kullanın.