Genel bakış
Aşağıda, geçiş anahtarı kaydıyla ilgili temel adımlara üst düzey bir genel bakış verilmiştir:
- Geçiş anahtarı oluşturma seçeneklerini tanımlayın. Bunları, geçiş anahtarı oluşturma çağrınıza (web'de
navigator.credentials.create
ve Android'decredentialManager.createCredential
) iletebilmeniz için istemciye gönderin. Kullanıcı, geçiş anahtarı oluşturulmasını onayladıktan sonra geçiş anahtarı oluşturma çağrısı çözümlenir ve bir kimlik bilgisiPublicKeyCredential
döndürür. - Kimlik bilgisini doğrulayın ve sunucuda saklayın.
Aşağıdaki bölümlerde her adımın ayrıntıları açıklanmaktadı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 tarafı kitaplığınızı kullanın. Bu özellik genellikle sizin için bu seçenekleri oluşturabilecek bir yardımcı program işlevi sunar. SimpleWebAuthn teklifleri (örneğin, generateRegistrationOptions
).
PublicKeyCredentialCreationOptions
, geçiş anahtarı oluşturmak için gereken her şeyi içermelidir: kullanıcı ve kısıtlanmış taraf hakkında bilgiler ve oluşturduğunuz kimlik bilgisinin özellikleriyle ilgili yapılandırma. Bunların tümünü tanımladıktan sonra, bunları FIDO sunucu tarafı kitaplığınızda PublicKeyCredentialCreationOptions
nesnesini oluşturmaktan sorumlu olan işleve gerektiği şekilde iletin.
PublicKeyCredentialCreationOptions
'lik alanların bazıları sabit değer olabilir. Diğerleri sunucuda dinamik olarak tanımlanmalıdır:
rpId
: Sunucudaki RP kimliğini doldurmak için web uygulamanızın ana makine adını veren sunucu tarafı işlevleri veya değişkenleri (ör.example.com
) kullanın.user.name
veuser.displayName
: Bu alanları doldurmak için oturum açmış kullanıcının oturum bilgilerini (veya kullanıcı kayıt sırasında geçiş anahtarı oluşturuyorsa yeni kullanıcı hesabı bilgilerini) kullanın.user.name
genellikle bir e-posta adresidir ve kısıtlanmış taraf için benzersizdir.user.displayName
kullanımı kolay bir ad. Tüm platformlarındisplayName
kullanmayacağını unutmayın.user.id
: Hesap oluşturulduktan sonra oluşturulan rastgele, benzersiz bir dizedir. Düzenlenebilir olabilecek bir kullanıcı adının aksine kalıcı olmalıdır. User-ID bir hesabı tanımlar, ancak kimliği tanımlayabilecek bilgiler (PII) içermemelidir. Muhtemelen sisteminizde zaten bir kullanıcı kimliği vardır, ancak gerekirse geçiş anahtarlarının kimliği tanımlayabilecek bilgiler (PII) içermemesi için özel olarak bir kimlik oluşturun.excludeCredentials
: Geçiş anahtarı sağlayıcıdan geçiş anahtarı oluşturulmasını önlemek için mevcut kimlik bilgisi kimliklerinin listesi. Bu alanı doldurmak için veritabanınızda bu kullanıcıya ait mevcut kimlik bilgilerini arayın. Zaten varsa yeni bir geçiş anahtarı oluşturulmasını önleme başlıklı makaleden ayrıntıları inceleyin.challenge
: Kimlik bilgisi kaydı söz konusu olduğunda, geçiş anahtarı sağlayıcısının kimliğini ve yayınladığı verileri doğrulamak için daha gelişmiş bir teknik olan onay yöntemini kullanmadığınız sürece bu soru geçerli olmaz. Ancak onay kullanmasanız bile giriş sorgulaması zorunlu bir alandır. Bu durumda, basit olması için bu sorgulamayı tek bir0
olarak ayarlayabilirsiniz. Kimlik doğrulama için güvenli giriş sorgulaması oluşturma talimatlarını Sunucu tarafı geçiş anahtarı kimlik doğrulaması başlıklı makalede bulabilirsiniz.
Kodlama ve kod çözme
![Sunucu tarafından gönderilen PublicKeyCredentialCreationOptions](https://developers-dot-devsite-v2-prod.appspot.com/identity/passkeys/developer-guides/server-registration/images/server-publicKeyCredentialCreationOptions.png?authuser=6&hl=tr)
PublicKeyCredentialCreationOptions
sunucu tarafından gönderildi. PublicKeyCredentialCreationOptions
öğesinin HTTPS üzerinden yayınlanabilmesi için challenge
, user.id
ve excludeCredentials.credentials
değerlerinin sunucu tarafında base64URL
olarak kodlanması gerekir.PublicKeyCredentialCreationOptions
, ArrayBuffer
alanları içerdiği için JSON.stringify()
tarafından desteklenmez. Bu, şu anda HTTPS üzerinden PublicKeyCredentialCreationOptions
yayınlamak için bazı alanların base64URL
kullanılarak sunucuda manuel olarak kodlanması ve ardından istemcide kodunun çözülmesi gerektiği anlamına gelir.
- Sunucuda, kodlama ve kod çözme işlemleri genellikle FIDO sunucu tarafı kitaplığınız tarafından gerçekleştirilir.
- İstemcide ise kodlama ve kod çözme işlemlerinin şu anda manuel olarak yapılması gerekir. Gelecekte daha kolay hale gelecektir: Seçenekleri JSON olarak
PublicKeyCredentialCreationOptions
biçimine dönüştürmek için bir yöntem kullanıma sunulacaktır. Chrome'da uygulamanın durumunu kontrol edin.
Örnek kod: Kimlik bilgisi oluşturma seçenekleri oluşturma
Örneklerimizde SimpleWebAuthn kitaplığını kullanıyoruz. Burada, ortak anahtar kimlik bilgisi seçeneklerinin oluşturulmasını bu komutun generateRegistrationOptions
işlevine devrediyoruz.
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 = 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
![Sunucu tarafından gönderilen PublicKeyCredentialCreationOptions](https://developers-dot-devsite-v2-prod.appspot.com/identity/passkeys/developer-guides/server-registration/images/server-publicKeyCredentialCreationOptions.png?authuser=6&hl=tr)
navigator.credentials.create
, PublicKeyCredential
nesnesi döndürür.navigator.credentials.create
istemcide başarıyla çözümlendiğinde geçiş anahtarı başarıyla oluşturulmuştur. Bir PublicKeyCredential
nesnesi döndürülür.
PublicKeyCredential
nesnesi, geçiş anahtarı sağlayıcısının istemcinin geçiş anahtarı oluşturma talimatına verdiği yanıtı temsil eden bir AuthenticatorAttestationResponse
nesnesi içerir. Kullanıcının kimliğini daha sonra doğrulamak için kısıtlanmış taraf olarak ihtiyaç duyacağınız yeni kimlik bilgisi bilgilerini içerir. AuthenticatorAttestationResponse
hakkında daha fazla bilgiyi Ek: AuthenticatorAttestationResponse
bölümünde bulabilirsiniz.
PublicKeyCredential
nesnesini sunucuya gönderin. Aldıktan sonra doğrulayın.
Bu doğrulama adımını FIDO sunucu tarafı kitaplığınıza aktarın. Bu amaçla genellikle bir yardımcı program işlevi sunar. SimpleWebAuthn teklifleri (örneğin, verifyRegistrationResponse
). Ek: Kayıt yanıtının doğrulanması başlıklı makaleden, arka planda neler olduğunu öğrenebilirsiniz.
Doğrulama başarılı olduktan sonra kullanıcının, söz konusu kimlik bilgileriyle ilişkili geçiş anahtarıyla kimlik doğrulaması yapabilmesi için kimlik bilgisi bilgilerini veritabanınızda depolayın.
Geçiş anahtarlarıyla ilişkili ortak anahtar kimlik bilgileri için özel bir tablo kullanın. Bir kullanıcının tek bir şifresi olabilir, ancak birden fazla geçiş anahtarı olabilir. Örneğin, Apple iCloud Anahtar Zinciri ile senkronize edilen bir geçiş anahtarı ve Google Şifre Yöneticisi aracılığıyla başka bir şifre anahtarı kullanılabilir.
Aşağıda, kimlik bilgilerini depolamak için kullanabileceğiniz bir örnek şema verilmiştir:
- Kullanıcılar tablosu:
user_id
: Birincil kullanıcı kimliği. Kullanıcının rastgele, benzersiz, kalıcı kimliği. Bunu Kullanıcılar tablonuz için birincil anahtar olarak kullanın.username
. Düzenlenebilir olabilecek, kullanıcı tanımlı bir kullanıcı adı.passkey_user_id
: Kayıt seçeneklerinizdeuser.id
ile gösterilen, geçiş anahtarına özel, kimliği tanımlayabilecek bilgiler (PII) içermeyen kullanıcı kimliği. Kullanıcı daha sonra kimlik doğrulaması yapmaya çalıştığında, kimlik doğrulayıcı,userHandle
içindeki kimlik doğrulama yanıtında bupasskey_user_id
öğesini kullanılabilir hale getirecektir.passkey_user_id
öğesini birincil anahtar olarak ayarlamamanızı öneririz. Birincil anahtarlar, yaygın bir şekilde kullanıldığından sistemlerde fiili kimlik bilgisi haline gelme eğilimindedir.
- Ortak anahtar kimlik bilgileri tablosu:
id
: Kimlik bilgisi kimliği. Bunu 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 bunu yabancı anahtar olarak kullanın.backed_up
: Geçiş anahtarı, geçiş anahtarı sağlayıcı tarafından senkronize ediliyorsa yedeklenir. Yedekleme durumunu saklamak, gelecektebacked_up
geçiş anahtarına sahip olan kullanıcıların şifrelerini bırakmayı düşünüyorsanız kullanışlıdır. Geçiş anahtarının yedeklenip yedeklenmediğiniauthenticatorData
ürünündeki işaretleri inceleyerek veya bu bilgilere kolayca erişebilmeniz için genellikle kullanılabilen bir FIDO sunucu tarafı kitaplık özelliğini kullanarak kontrol edebilirsiniz. Yedek uygunluğu depolamak, potansiyel kullanıcı sorgularını ele almanıza yardımcı olabilir.name
: İsteğe bağlı olarak, kullanıcıların kimlik bilgileri için özel adlar verebilmesine olanak tanıyan kimlik bilgisi görünen adı.transports
: Bir dizi transspor Aktarımların depolanması, kimlik doğrulama kullanıcı deneyimi için yararlıdır. Aktarımlar mevcut olduğunda tarayıcı uygun şekilde davranabilir ve geçiş anahtarı sağlayıcısının istemcilerle iletişim kurmak için kullandığı aktarımla eşleşen bir kullanıcı arayüzü gösterebilir. Bu, özellikle deallowCredentials
alanının boş olmadığı yeniden kimlik doğrulama kullanım alanları için geçerlidir.
Geçiş anahtarı sağlayıcısı, kimlik bilgisi oluşturma zamanı ve son kullanım zamanı gibi öğeler de dahil olmak üzere diğer bilgiler kullanıcı deneyimi açısından saklanmasına yardımcı olabilir. Daha fazla bilgi için Geçiş anahtarı kullanıcı arayüzü tasarımı konusuna bakın.
Örnek kod: kimlik bilgilerini depolama
Örneklerimizde SimpleWebAuthn kitaplığını kullanıyoruz.
Bu bölümde, kayıt yanıtı doğrulamasını verifyRegistrationResponse
işlevine devrediyoruz.
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 { credentialPublicKey, credentialID } = registrationInfo;
// Existing, signed-in user
const { user } = res.locals;
// Save the credential
await Credentials.update({
id: base64CredentialID,
publicKey: base64PublicKey,
// Optional: set the platform as a default name for the credential
// (example: "Pixel 7")
name: req.useragent.platform,
transports: response.response.transports,
passkey_user_id: user.passkey_user_id,
backed_up: registrationInfo.credentialBackedUp
});
// 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
, istemci verilerinin bir JSON sürümüdür. Bu sürüm, web'deki veriler olarak tarayıcının gördüğü şekildedir. Kısıtlanmış taraf kaynağını, giriş sorgulamasını ve istemci bir Android uygulamasıysaandroidPackageName
bilgisini içerir. Kısıtlanmış taraf olarakclientDataJSON
okuması,create
isteği yapılırken tarayıcının gördüğü bilgilere erişmenize olanak tanır.response.attestationObject
şu iki bilgi içerir:attestationStatement
. Onay kullanmadığınız sürece uygun değildir.authenticatorData
, geçiş anahtarı sağlayıcısının gördüğü verilerdir. Kısıtlanmış taraf olarak okumaauthenticatorData
izni, geçiş anahtarı sağlayıcısının gördüğü vecreate
isteği sırasında döndürülen verilere erişmenizi sağlar.
authenticatorData
, yeni oluşturulan geçiş anahtarıyla ilişkili ortak anahtar kimlik bilgisi hakkında önemli bilgileri içerir:
- Ortak anahtar kimlik bilgilerinin kendisi ve benzersiz kimlik bilgisi kimliği.
- Kimlik bilgisiyle ilişkilendirilen RP kimliği.
- Geçiş anahtarı oluşturulduğunda kullanıcı durumunu (kullanıcının gerçekten mevcut olup olmadığı ve başarıyla doğrulanıp doğrulanmadığı) açıklayan işaretler (bkz.
userVerification
). - Geçiş anahtarı sağlayıcısını tanımlayan AAGUID. Geçiş anahtarı sağlayıcısının gösterilmesi, özellikle birden fazla geçiş anahtarı sağlayıcısında hizmetiniz için kayıtlı bir geçiş anahtarı varsa kullanıcılarınız için yararlı olabilir.
authenticatorData
, attestationObject
içinde iç içe yerleştirilmiş olsa da içerdiği bilgiler, onay kullanıp kullanmadığınızdan bağımsız olarak geçiş anahtarı uygulamanız için gereklidir. authenticatorData
kodlanmıştır ve ikili biçimde kodlanmış alanlar içerir. Sunucu tarafı kitaplığınız genellikle ayrıştırma ve kod çözme işlemlerini gerçekleştirir. Sunucu tarafı kitaplığı kullanmıyorsanız sunucu tarafında işlerin ayrıştırılması ve kodunun çözülmesi için gerekenden tasarruf etmek için getAuthenticatorData()
istemci tarafını kullanmayı düşünün.
Ek: kayıt yanıtının doğrulanması
Kayıt yanıtının doğrulanması, arka planda aşağıdaki kontrollerden oluşur:
- RP kimliğinin sitenizle eşleştiğinden emin olun.
- İstek kaynağının siteniz için beklenen bir kaynak (ana site URL'si, Android uygulaması) olduğundan emin olun.
- Kullanıcı doğrulaması gerekiyorsa
authenticatorData.uv
kullanıcı doğrulama işaretinintrue
olduğundan emin olun. Geçiş anahtarları için kullanıcının varlığı her zaman zorunludur. Bu nedenle,authenticatorData.up
kullanıcı varlığı işaretinintrue
olup olmadığını kontrol edin. - Müşterinin, verdiğiniz giriş sorgulamasını sağlayıp sağlayamadığını kontrol edin. Onay kullanmıyorsanız bu kontrol önemsizdir. Ancak bu denetimi uygulamak en iyi uygulamadır: İleride onay kullanmaya karar verirseniz kodunuzun hazır olmasını sağlar.
- Kimlik bilgisi kimliğinin herhangi bir kullanıcı için henüz kaydedilmediğinden emin olun.
- Geçiş anahtarı sağlayıcısının kimlik bilgisini oluşturmak için kullandığı algoritmanın sizin listelediğiniz bir algoritma olduğunu doğrulayın (
publicKeyCredentialCreationOptions.pubKeyCredParams
öğesinin heralg
alanında, genellikle sunucu tarafı kitaplığınızda tanımlanır ve sizin tarafınızdan görülemez). Bu, kullanıcıların yalnızca izin vermeyi seçtiğiniz algoritmalarla kaydolabilmelerini sağlar.
Daha fazla bilgi edinmek için SimpleWebAuthn'un verifyRegistrationResponse
için kaynak kodunu kontrol edin veya spesifikasyondaki doğrulamaların tam listesini inceleyin.