Daha fazla bilgi için sahte e-posta sağlayıcı demo kodunu inceleyebilir ve E-posta Doğrulama API'si ile E-posta Doğrulama Protokolü önerilerindeki veren adımlarına bakabilirsiniz.
Tarayıcı davranışını tetikleyen taraf güvenen taraf sitesi olduğundan, kart sağlayıcı olarak, kaynak denemesine kaydolmanız veya jeton sağlamanız gerekmez. Uç noktalarınızın bu isteklere yanıt verecek şekilde yapılandırıldığından emin olun.
Kart sağlayıcı keşfini yapılandırma
Tarayıcıların, alanınıza ait bir e-posta adresi seçildiğinde doğrulama uç noktalarınızı otomatik olarak keşfetmesine izin vermek için DNS ve .well-known HTTP uç noktası kullanarak yapılandırmanızı kullanıma sunun.
DNS temsilci kaydını yapılandırma
E-posta alanınızda, doğrulama yetkisini veren kimlik sağlayıcınıza devreden bir DNS TXT kaydı yapılandırın. Bu tanımlayıcılar, altyapınıza bağlı olarak aynı alanı kullanabilir.
Kayıt Biçimi: _email-verification.<email-domain>
Örnek alan dosyası:
_email-verification.example.com IN TXT "iss=accounts.issuer.example"
.well-known/email-verification uç noktası barındırma
Düzenleyen alanınızda /.well-known/ yolu altında bir JSON meta veri dosyası barındırın.
Bu dosyada, düzenleme özellikleriniz ve altyapınızın desteklediği kriptografik imzalama algoritmaları özetlenir.
Uç nokta: https://<issuer-domain>/.well-known/email-verification
Örnek yanıt:
{
"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 uç noktası barındırma
Federated Credentials (FedCM) API'nin bir parçası olarak ek bir .well-known JSON kaynağı uygulamış olabilirsiniz. Bu kaynak, hesap uç noktanıza ve giriş URL'nize bağlantılar sağlar.
Uç nokta: https://<domain>/.well-known/web-identity
Örnek yanıt:
{
"accounts_endpoint": "https://accounts.issuer.example/accounts",
"login_url": "https://accounts.issuer.example/login"
}
Hesap uç noktası kullanma
FedCM API'deki hesaplar uç noktası, şu anda oturum açılmış hesapların listesini sağlar. Aşağıdaki örnekte minimum düzeyde bir yanıt gösterilmektedir. Daha fazla bilgi için kimlik sağlayıcı uygulama kılavuzuna bakın.
Uç nokta: .well-known/web-identity içinde belirtildiği gibi
Aşağıda örnek bir yanıt verilmiştir:
{
"accounts": [
{
"id": "demo-example",
"name": "Demo User",
"email": "demo@example.com",
"given_name": "Demo"
}
]
}
Login Status API ile entegrasyon
Kullanıcının sağlayıcıyla etkin bir oturumu olmalı ve Login Status API'yi kullanarak bunu tarayıcıya bildirmeniz gerekir.
Bir kullanıcı başarılı bir şekilde oturum açtığında veya oturumu kapattığında eşleşen HTTP yanıt başlığını yayınlayın:
Set-Login: logged-in
Set-Login: logged-out
Alternatif olarak, web uygulamanızda JavaScript kullanarak durumu güncelleyin:
navigator.login.setStatus("logged-in");
navigator.login.setStatus("logged-out");
Yayınlama isteklerini işleme
issuance_endpoint, application/json POST isteği alıyor. Bu istekte email anahtarı ve Signature, Signature-Input ve Signature-Key için HTTP mesajı imzaları üst bilgileri yer alıyor.
Ortamınız için yapılandırılmış üstbilgileri ve HTTP mesaj imzalarını destekleyen bir kitaplık kullanın. Node.js'de structured-headers ve http-message-sig kullanabilirsiniz.
Tam istek biçimi:
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"}
İsteği ayrıştırın ve doğrulayın:
- Oturum kimlik doğrulaması: İstekle birlikte gönderilen birinci taraf oturum çerezlerinizi doğrulayın. Kullanıcının kimliği doğrulanmalıdır.
Sec-Fetch-Destüstbilgisi:email-verificationolarak ayarlayın.- HTTP Mesaj İmzaları:
Signature-Keyiçindeki kısa ömürlü ortak anahtarı kullanarak istek imzasını doğrulayın veContent-Digestöğesini onaylayın. - Yük: JSON gövdesi, doğrulama için istenen
emaildizesini içerir.
Verilme yanıtı
Oturum ve istek jetonu başarıyla doğrulandıktan sonra, platformunuz için uygun kitaplıkları kullanarak JSON olarak döndürülen imzalı bir Selective Disclosure JWT (SD-JWT) oluşturun. Örneğin, Node için @sd-jwt/core ve jose kullanabilirsiniz.
Ham yük biçimi şu şekilde görünmelidir:
{
"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
}
Jetonu oluşturun, imzalayın ve döndürün:
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);
Elde edilen yanıt gövdesi şuna benzer:
{
"issuance_token": "tOkEn123tOkEn123tOkEn123...~"
}
E-posta doğrulama jetonunu oluşturup imzaladıktan sonra tarayıcı, bunu doğrulama için doğrulayıcı siteye iletir.
Sorun giderme
Tarayıcı, uç noktalarınıza ulaşmıyorsa veya verilen jetonları reddediyorsa aşağıdaki yaygın sorunları kontrol edin:
Tarayıcı hiçbir zaman accounts_endpoint veya issuance_endpoint işlevini çağırmaz.
- Oturum açma durumu ayarlanmadı: Chrome, yalnızca kullanıcının oturum açtığını biliyorsa uç noktalarınıza sorgu gönderir. Oturum açma akışınızın
Set-Login: logged-inHTTP üstbilgisini ayarladığından veyanavigator.login.setStatus("logged-in")işlevini çağırdığından emin olun. - Oturum çerezleri engellendi (
SameSite=None): Tarayıcı,accounts_endpointveissuance_endpointöğelerinizi farklı bir sitedeki güvenilen taraftan getiriyor. Bunlar siteler arası istekler olduğundan oturum çerezinizSameSite=None; Secureiçermelidir.SameSite=Laxçerezi, aynı site doğrulayıcıda test edilirken çalışır ancak siteler arası isteklerde atlanır. - Keşif veya hesap eşleşmemesi:
_email-verification.<email-domain>'nin tek bir TXT kaydı (iss=<issuer-domain>,https://olmadan) döndürdüğünü, her iki.well-knownuç noktasınınContent-Type: application/jsondöndürdüğünü veaccounts_endpointyanıtının,email'si girilen adresle eşleşen bir hesap içerdiğini doğrulayın.
Düzenleme isteği doğrulanamadı
Sec-Fetch-Destüstbilgi yazımı: Chrome 154 ve sonraki sürümlerindeSec-Fetch-Dest: email-verification(tireli) gönderilirken Chrome 153'teemailverification(tiresiz) gönderiliyordu. Kullanıma sunma sırasında her iki değeri de kabul edin.- Proxy'nin arkasında HTTP mesaj imzası (
@authority) eşleşmemesi: RFC 9421 imzası doğrulanırken@authoritybileşeni, herkese açık ana makineyi yansıtır. Sunucunuz bir ters proxy'nin veya yük dengeleyicinin arkasında bulunuyorsa doğrulama URL'sini dahili ana makine adı yerineX-Forwarded-Host(veya herkese açık kaynağınız) kullanarak yeniden oluşturun ve JSON ayrıştırmadan önce ham istek gövdesi baytları üzerindeContent-Digesthesaplayın.
Tarayıcı, döndürülen issuance_token öğesini reddediyor
- Değiştirilmiş veya kanonikleştirilmiş
emailtalebi: Chrome 156'dan itibaren tarayıcı, EVTemailtalebinin istenenemailile bire bir eşleşip eşleşmediğini kontrol eder. Arka uçunuz adresi kanonik bir hesap biçimine normalleştirirse (ör.First.Last@example.comistendiğindefirst.LAST@example.comdöndürülürse) Chrome, jetonu bırakır. İsteği kullanıcının hesabıyla eşleştirin ancak istek gövdesinde alınan tamemaildizesini döndürün. - Sondaki tilde (
~) eksik: Hiç açıklama olmasa bile tarayıcının<KB-JWT>ekleyebilmesi içinissuance_token, sondaki tilde (<Issuer-signed-JWT>~) ile biten geçerli bir SD-JWT olmalıdır. - Eşleşmeyen
issveyacnf.jwk: EVTisstalebinin,.well-known/email-verificationmeta verilerinizle eşleşen tam HTTPS kaynağı (https://<issuer-domain>, sondaki eğik çizgi yok) olduğundan vecnf.jwk'ninSignature-Keyüstbilgisinden tarayıcının kısa ömürlü ortak anahtarını yerleştirdiğinden emin olun.