Genel Bakış
Geçiş anahtarı kaydıyla ilgili temel adımlara genel bir bakış:

- Geçiş anahtarı oluşturma seçeneklerini tanımlayın. Bunları istemciye gönderin. Böylece, bunları geçiş anahtarı oluşturma çağrınıza iletebilirsiniz: WebAuthn API çağrısı
navigator.credentials.createweb'de vecredentialManager.createCredentialAndroid'de. Kullanıcı, geçiş anahtarının oluşturulmasını onayladıktan sonra geçiş anahtarı oluşturma çağrısı çözülür vePublicKeyCredentialkimlik bilgisi döndürülür. - Kimlik bilgisini doğrulayın ve sunucuda saklayın.
Aşağıdaki bölümlerde her adımın ayrıntıları ele alınmaktadır.
Kimlik bilgisi oluşturma seçenekleri oluşturma
Sunucuda atmanız gereken ilk adım, bir PublicKeyCredentialCreationOptions nesnesi oluşturmaktır.
Bunu yapmak için FIDO sunucu taraflı kitaplığınızı kullanın. Genellikle bu seçenekleri sizin için oluşturabilecek bir yardımcı işlev sunar. Örneğin, SimpleWebAuthn generateRegistrationOptions sunar.
PublicKeyCredentialCreationOptions, geçiş anahtarı oluşturmak için gereken her şeyi (kullanıcı ve RP ile ilgili bilgiler ve oluşturduğunuz kimlik bilgilerinin özellikleriyle ilgili bir yapılandırma) içermelidir. Bunların hepsini tanımladıktan sonra, PublicKeyCredentialCreationOptions nesnesini oluşturmaktan sorumlu olan FIDO sunucu tarafı kitaplığınızdaki işleve gerektiği şekilde iletin.
PublicKeyCredentialCreationOptions alanlarından bazıları sabit olabilir. Diğerleri sunucuda dinamik olarak tanımlanmalıdır:
rpId: Sunucudaki RP kimliğini doldurmak içinexample.comgibi web uygulamanızın ana makine adını veren sunucu tarafı işlevlerini veya değişkenlerini kullanın.user.nameveuser.displayName: Bu alanları doldurmak için oturum açmış kullanıcınızın oturum bilgilerini (veya kullanıcı kayıt sırasında geçiş anahtarı oluşturuyorsa yeni kullanıcı hesabı bilgilerini) kullanın.user.namegenellikle bir e-posta adresidir ve RP için benzersizdir.user.displayName, kullanıcı dostu bir addır.displayName, tüm platformlarda kullanılmaz.user.id: Hesap oluşturulduğunda oluşturulan rastgele ve benzersiz bir dize. Düzenlenebilir bir kullanıcı adının aksine kalıcı olmalıdır. Kullanıcı kimliği bir hesabı tanımlar ancak kimliği tanımlayabilecek bilgiler (PII) içermemelidir. Sisteminizde muhtemelen zaten bir kullanıcı kimliği vardır. Ancak gerekirse kişisel olarak tanımlanabilir bilgiler içermemesi için geçiş anahtarlarına özel bir kullanıcı kimliği oluşturun.excludeCredentials: Geçiş anahtarı sağlayıcısından geçiş anahtarının kopyalanmasını önlemek için mevcut kimlik bilgilerinin kimliklerinin listesi. Bu alanı doldurmak için veritabanınızda bu kullanıcının mevcut kimlik bilgilerini arayın. Ayrıntıları Bir geçiş anahtarı zaten varsa yenisinin oluşturulmasını engelleme başlıklı makalede bulabilirsiniz.challenge: Kimlik bilgisi kaydı için, geçiş anahtarı sağlayıcının kimliğini ve yaydığı verileri doğrulamak üzere daha gelişmiş bir teknik olan onaylama kullanmadığınız sürece sorgulama geçerli değildir. Ancak, onay kullanmasanız bile meydan okuma alanı zorunlu olmaya devam eder. Kimlik doğrulama için güvenli bir sorgu oluşturmayla ilgili talimatları Sunucu tarafı geçiş anahtarı kimlik doğrulaması başlıklı makalede bulabilirsiniz.
Kodlama ve kod çözme
Sunucu tarafından gönderilen PublicKeyCredentialCreationOptions. challenge, user.id ve excludeCredentials.credentials, base64URL olarak sunucu tarafında kodlanmalıdır. Böylece PublicKeyCredentialCreationOptions, HTTPS üzerinden yayınlanabilir.PublicKeyCredentialCreationOptions, ArrayBuffer olan alanlar içerdiğinden JSON.stringify() tarafından desteklenmez. Bu nedenle, şu anda PublicKeyCredentialCreationOptions öğesini HTTPS üzerinden sunmak için bazı alanların sunucuda base64URL kullanılarak manuel olarak kodlanması ve ardından istemcide kodunun çözülmesi gerekir.
- Sunucuda kodlama ve kod çözme işlemleri genellikle FIDO sunucu tarafı kitaplığınız tarafından yapılır.
- İstemcide kodlama ve kod çözme işlemleri şu anda manuel olarak yapılmalıdır. Gelecekte bu işlem daha kolay olacaktır: Seçenekleri JSON olarak
PublicKeyCredentialCreationOptionsbiçimine dönüştürmek için bir yöntem kullanıma sunulacaktır. Chrome'daki uygulamanın durumunu kontrol edin.
Örnek kod: Kimlik bilgisi oluşturma seçenekleri oluşturma
Örneklerimizde SimpleWebAuthn kitaplığını kullanıyoruz. Burada, herkese açık anahtar kimlik bilgisi seçeneklerinin oluşturulması generateRegistrationOptions işlevine devredilir.
import {
generateRegistrationOptions,
verifyRegistrationResponse,
generateAuthenticationOptions,
verifyAuthenticationResponse
} from '@simplewebauthn/server';
import { isoBase64URL } from '@simplewebauthn/server/helpers';
router.post('/registerRequest', csrfCheck, sessionCheck, async (req, res) => {
const { user } = res.locals;
// Ensure you nest verification function calls in try/catch blocks.
// If something fails, throw an error with a descriptive error message.
// Return that message with an appropriate error code to the client.
try {
// `excludeCredentials` prevents users from re-registering existing
// credentials for a given passkey provider
const excludeCredentials = [];
const credentials = Credentials.findByUserId(user.id);
if (credentials.length > 0) {
for (const cred of credentials) {
excludeCredentials.push({
id: isoBase64URL.toBuffer(cred.id),
type: 'public-key',
transports: cred.transports,
});
}
}
// Generate registration options for WebAuthn create
const options = await generateRegistrationOptions({
rpName: process.env.RP_NAME,
rpID: process.env.HOSTNAME,
userID: user.id,
userName: user.username,
userDisplayName: user.displayName || '',
attestationType: 'none',
excludeCredentials,
authenticatorSelection: {
authenticatorAttachment: 'platform',
requireResidentKey: true
},
});
// Keep the challenge in the session
req.session.challenge = options.challenge;
return res.json(options);
} catch (e) {
console.error(e);
return res.status(400).send({ error: e.message });
}
});
Ortak anahtarı saklama
navigator.credentials.create, PublicKeyCredential nesnesini döndürür.navigator.credentials.create istemcide başarıyla çözüldüğünde geçiş anahtarının başarıyla oluşturulduğu anlamına gelir. PublicKeyCredential nesnesi döndürülür.
PublicKeyCredential nesnesi, istemcinin geçiş anahtarı oluşturma talimatına geçiş anahtarı sağlayıcısının yanıtını temsil eden bir AuthenticatorAttestationResponse nesnesi içerir. Bu yanıt, kullanıcının kimliğini daha sonra doğrulamanız için RP olarak ihtiyacınız olan yeni kimlik bilgisi hakkında bilgiler içerir. AuthenticatorAttestationResponse hakkında daha fazla bilgiyi Ek: AuthenticatorAttestationResponse bölümünde bulabilirsiniz.
PublicKeyCredential nesnesini sunucuya gönderin. Kartı aldıktan sonra doğrulayın.
Bu doğrulama adımını FIDO sunucu tarafı kitaplığınıza devredin. Bu amaçla genellikle bir yardımcı işlev sunar. Örneğin, SimpleWebAuthn verifyRegistrationResponse sunar. Ek: Kayıt yanıtının doğrulanması bölümünde arka planda neler olduğunu öğrenin.
Doğrulama başarılı olduktan sonra, kullanıcının daha sonra bu kimlik bilgisiyle ilişkili geçiş anahtarıyla kimliğini doğrulayabilmesi için kimlik bilgisi bilgilerini veritabanınızda saklayın.
Geçiş anahtarlarıyla ilişkili ortak anahtar kimlik bilgileri için özel bir tablo kullanın. Bir kullanıcının yalnızca tek bir şifresi olabilir ancak birden fazla geçiş anahtarı olabilir. Örneğin, Apple iCloud Anahtar Zinciri aracılığıyla senkronize edilen bir geçiş anahtarı ve Google Şifre Yöneticisi aracılığıyla senkronize edilen bir geçiş anahtarı.
Kimlik bilgisi saklamak için kullanabileceğiniz örnek bir şema aşağıda verilmiştir:

- Kullanıcılar tablosu:
user_id: Birincil kullanıcı kimliği. Kullanıcı için rastgele, benzersiz ve kalıcı bir kimlik. Bunu Kullanıcılar tablonuz için birincil anahtar olarak kullanın.username. Kullanıcı tanımlı ve düzenlenebilir bir kullanıcı adı.passkey_user_id: Kayıt seçeneklerinizdeuser.idile gösterilen, geçiş anahtarına özel, kimliği tanımlayabilecek bilgiler içermeyen kullanıcı kimliği. Kullanıcı daha sonra kimlik doğrulamaya çalıştığında, kimlik doğrulayıcı bupasskey_user_iddeğeriniuserHandlekimlik doğrulama yanıtında kullanılabilir hale getirir.passkey_user_idsimgesini birincil anahtar olarak ayarlamamanızı öneririz. Birincil anahtarlar, yoğun olarak kullanıldıkları için sistemlerde fiili olarak kimliği tanımlayabilecek bilgiler haline gelir.
- Ortak anahtar kimlik bilgileri tablosu:
id: Kimlik bilgisi numarası. Bunu Public key credentials (Ortak anahtar kimlik bilgileri) tablonuz için birincil anahtar olarak kullanın.public_key: Kimlik bilgisinin ortak anahtarı.passkey_user_id: Kullanıcılar tablosuyla bağlantı oluşturmak için yabancı anahtar olarak kullanın.backed_up: Geçiş anahtarı sağlayıcı tarafından senkronize edilen geçiş anahtarları yedeklenir.backed_upgeçiş anahtarı olan kullanıcılar için gelecekte şifreleri bırakmayı düşünüyorsanız yedekleme durumunu saklamak faydalı olur. Geçiş anahtarının yedeklenip yedeklenmediğiniauthenticatorDataiçindeki BE işaretini inceleyerek veya genellikle bu bilgilere kolayca erişmenizi sağlayan bir FIDO sunucu tarafı kitaplık özelliğini kullanarak kontrol edebilirsiniz. Yedekleme uygunluğu bilgilerini saklamak, olası kullanıcı sorgularını yanıtlamak için faydalı olabilir.name: İsteğe bağlı olarak, kullanıcıların kimlik bilgilerine özel adlar vermesini sağlamak için kimlik bilgilerinin görünen adı.transports: Taşıma dizisi. Taşıma işlemlerini depolamak, kimlik doğrulama kullanıcı deneyimi için yararlıdır. Aktarım kullanılabilir olduğunda tarayıcı buna göre davranabilir ve geçiş anahtarı sağlayıcının istemcilerle iletişim kurmak için kullandığı aktarıma uygun bir kullanıcı arayüzü gösterebilir. Özellikle deallowCredentialsdeğerinin boş olmadığı yeniden kimlik doğrulama kullanım alanlarında bu durum geçerlidir.
Geçiş anahtarı sağlayıcı, kimlik bilgisi oluşturma zamanı ve son kullanma zamanı gibi öğeler de dahil olmak üzere, kullanıcı deneyimi amacıyla depolanması faydalı olabilecek başka bilgiler de vardır. Daha fazla bilgiyi Geçiş anahtarı kullanıcı arayüzü tasarımı başlıklı makalede bulabilirsiniz.
Örnek kod: kimlik bilgisini saklama
Örneklerimizde SimpleWebAuthn kitaplığını kullanıyoruz.
Burada, kayıt yanıtı doğrulama işlevini verifyRegistrationResponse işlevine devrederiz.
import { isoBase64URL } from '@simplewebauthn/server/helpers';
router.post('/registerResponse', csrfCheck, sessionCheck, async (req, res) => {
const expectedChallenge = req.session.challenge;
const expectedOrigin = getOrigin(req.get('User-Agent'));
const expectedRPID = process.env.HOSTNAME;
const response = req.body;
// This sample code is for registering a passkey for an existing,
// signed-in user
// Ensure you nest verification function calls in try/catch blocks.
// If something fails, throw an error with a descriptive error message.
// Return that message with an appropriate error code to the client.
try {
// Verify the credential
const { verified, registrationInfo } = await verifyRegistrationResponse({
response,
expectedChallenge,
expectedOrigin,
expectedRPID,
requireUserVerification: false,
});
if (!verified) {
throw new Error('Verification failed.');
}
const {
aaguid,
credentialPublicKey,
credentialID,
credentialBackedUp
} = registrationInfo;
// Name the credential based on AAGUID
const name =
aaguid === undefined ||
aaguid === '000000-0000-0000-0000-00000000' ?
req.useragent?.platform : aaguids[aaguid].name;
const base64CredentialID = isoBase64URL.fromBuffer(credentialID);
const base64PublicKey = isoBase64URL.fromBuffer(credentialPublicKey);
// Existing, signed-in user
const { user } = res.locals;
// Save the credential
await Credentials.update({
id: base64CredentialID,
passkey_user_id: user.passkey_user_id,
publicKey: base64PublicKey,
name,
aaguid,
transports: response.response.transports,
backed_up: credentialBackedUp,
registered_at: new Date().getTime()
});
// Kill the challenge for this session
delete req.session.challenge;
return res.json(user);
} catch (e) {
delete req.session.challenge;
console.error(e);
return res.status(400).send({ error: e.message });
}
});
Ek: AuthenticatorAttestationResponse
AuthenticatorAttestationResponse iki önemli nesne içerir:
response.clientDataJSON, web'de tarayıcı tarafından görülen veriler olan istemci verilerinin JSON sürümüdür. Bu, RP kaynağını, sorguyu ve istemcinin bir Android uygulaması olup olmadığını içerir. Bir RP olarakclientDataJSONokumak, tarayıcınıncreateisteği sırasında gördüğü bilgilere erişmenizi sağlar.androidPackageNameresponse.attestationObjectiki bilgi içerir:attestationStatement. Bu, onay kullanmadığınız sürece alakalı değildir.authenticatorData, geçiş anahtarı sağlayıcısı tarafından görülen verilerdir. RP olarak okuma işlemi,authenticatorDataisteği sırasında geçiş anahtarı sağlayıcı tarafından görülen ve döndürülen verilere erişmenizi sağlar.create
authenticatorDataYeni oluşturulan geçiş anahtarıyla ilişkili ortak anahtar kimlik bilgisi hakkında önemli bilgiler içerir:
- Ortak anahtar kimlik bilgisi ve bu kimlik bilgisi için benzersiz bir kimlik bilgisi kimliği.
- Kimlik bilgisiyle ilişkili RP kimliği.
- Geçiş anahtarı oluşturulduğunda kullanıcı durumunu açıklayan işaretler: Kullanıcının gerçekten mevcut olup olmadığı ve kullanıcının başarıyla doğrulanıp doğrulanmadığı (userVerification derinlemesine incelemesi bölümüne bakın).
- AAGUID, Google Şifre Yöneticisi gibi geçiş anahtarı sağlayıcısının tanımlayıcısıdır. AAGUID'ye göre geçiş anahtarı sağlayıcısını belirleyebilir ve adı geçiş anahtarı yönetimi sayfasında gösterebilirsiniz. (bkz. AAGUID ile geçiş anahtarı sağlayıcısını belirleme)
authenticatorData, attestationObject içinde yer alsa da içerdiği bilgiler, onaylama kullanıp kullanmadığınıza bakılmaksızın geçiş anahtarı uygulamanız için gereklidir. authenticatorData kodlanmıştır ve ikili biçimde kodlanmış alanlar içerir. Genellikle sunucu tarafı kitaplığınız ayrıştırma ve kod çözme işlemlerini gerçekleştirir. Sunucu tarafı kitaplığı kullanmıyorsanız sunucu tarafında ayrıştırma ve kod çözme işlemlerinden tasarruf etmek için getAuthenticatorData() istemci tarafı kitaplığından yararlanabilirsiniz.
Ek: Kayıt yanıtının doğrulanması
Kayıt yanıtının doğrulanması için arka planda aşağıdaki kontroller yapılır:
- RP kimliğinin sitenizle eşleştiğinden emin olun.
- İsteğin kaynağının siteniz için beklenen bir kaynak (ana site URL'si, Android uygulaması) olduğundan emin olun.
- Kullanıcı doğrulaması gerektiriyorsanız kullanıcı doğrulama işaretinin
authenticatorData.uvtrueolduğundan emin olun. - Kullanıcı varlığı işareti
authenticatorData.upgenellikletrueolmalıdır ancak kimlik bilgisi koşullu olarak oluşturulmuşsafalseolması beklenir. - İstemcinin, verdiğiniz testi sağlayabildiğini kontrol edin. Onay kullanmıyorsanız bu kontrol önemli değildir. Ancak bu kontrolü uygulamak en iyi uygulamadır. Gelecekte onay kullanmaya karar verirseniz kodunuzun hazır olmasını sağlar.
- Kimlik bilgisi kimliğinin henüz herhangi bir kullanıcı için kaydedilmediğinden emin olun.
- Geçiş anahtarı sağlayıcısı tarafından kimlik bilgisi oluşturmak için kullanılan algoritmanın, sizin listelediğiniz bir algoritma (genellikle sunucu tarafı kitaplığınızda tanımlanan ve sizin tarafınızdan görünmeyen
publicKeyCredentialCreationOptions.pubKeyCredParams'nin heralgalanında) olduğunu doğrulayın. Bu sayede kullanıcılar yalnızca izin vermeyi seçtiğiniz algoritmalarla kayıt olabilir.
Daha fazla bilgi edinmek için SimpleWebAuthn'in verifyRegistrationResponse kaynak kodunu inceleyin veya spesifikasyondaki doğrulama listesinin tamamına göz atın.