Genel Bakış
Geçiş anahtarı kaydıyla ilgili önemli adımlara genel bakışı aşağıda bulabilirsiniz:
- Geçiş anahtarı oluşturma seçeneklerini tanımlayın. Bu şifreleri istemciye göndererek geçiş anahtarı oluşturma görüşmenize iletebilirsiniz: WebAuthn API çağrısı (web'de
navigator.credentials.create
ve Android'decredentialManager.createCredential
). Kullanıcı, geçiş anahtarı oluşturma işlemini onayladıktan sonra geçiş anahtarı oluşturma çağrısı çözümlenir ve kimlik bilgisiPublicKeyCredential
döndürülür. - Kimlik bilgisini doğrulayın ve sunucuda depolayın.
Aşağıdaki bölümlerde her bir adımın ayrıntıları açıklanmaktadır.
Kimlik bilgisi oluşturma seçenekleri oluşturma
Sunucuda uygulamanız gereken ilk adım bir PublicKeyCredentialCreationOptions
nesnesi oluşturmaktır.
Bunu yapmak için FIDO sunucu tarafı kitaplığınızı kullanın. 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ı, kısıtlanmış taraf hakkında bilgi ve oluşturduğunuz kimlik bilgisinin özelliklerine ilişkin yapılandırma. Bunların tümünü tanımladıktan sonra, FIDO sunucu tarafı kitaplığınızda PublicKeyCredentialCreationOptions
nesnesini oluşturmaktan sorumlu olan işleve gerektiği şekilde iletin.
Bazı PublicKeyCredentialCreationOptions
. alanları sabit olabilir. Diğerleri sunucuda dinamik olarak tanımlanmalıdır:
rpId
: Sunucuda RP kimliğini doldurmak için sunucu tarafı işlevlerini veya web uygulamanızın ana makine adını verenexample.com
gibi değişkenleri kullanın.user.name
veuser.displayName
: Bu alanları doldurmak için oturum açan kullanıcının oturum bilgilerini (veya kullanıcı, kaydolurken 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ıcı dostu bir addır. Tüm platformlarındisplayName
kullanmayacağını unutmayın.user.id
: Hesap oluşturulduktan sonra üretilen rastgele, benzersiz bir dize. Düzenlenebilir olan 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. Sisteminizde muhtemelen zaten bir User-ID vardır ancak gerekirse kimliği tanımlayabilecek bilgiler içermemesi için geçiş anahtarları için özel olarak bir kullanıcı kimliği oluşturun.excludeCredentials
: Mevcut kimlik bilgilerinin listesi Geçiş anahtarı sağlayıcısından geçiş anahtarının yinelenmesini önleyen kimlikler. Bu alanı doldurmak için veritabanınızda bu kullanıcının mevcut kimlik bilgilerini arayın. Mevcutsa yeni geçiş anahtarı oluşturulmasını engelle başlıklı makaleyi inceleyin.challenge
: 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 özelliğini kullanmadığınız sürece kimlik bilgisi kaydında sorun yaşamazsınız. Ancak onay kullanmasanız bile sorgulama yine de zorunlu bir alandır. Bu durumda, kolaylık olması açısından bu zorluğu tek bir0
olarak ayarlayabilirsiniz. Kimlik doğrulama için güvenli sorgulama oluşturma talimatlarını Sunucu tarafı geçiş anahtarı kimlik doğrulaması bölümünde bulabilirsiniz.
Kodlama ve kodu çözme
![Sunucu tarafından gönderilen PublicKeyCredentialCreationOptions](https://google-developers.gonglchuangl.net/identity/passkeys/developer-guides/server-registration/images/server-publicKeyCredentialCreationOptions.png?authuser=0&hl=tr)
PublicKeyCredentialCreationOptions
gönderildi. PublicKeyCredentialCreationOptions
adresinin HTTPS üzerinden teslim edilebilmesi için challenge
, user.id
ve excludeCredentials.credentials
sunucu tarafında base64URL
olarak kodlanmalıdır.PublicKeyCredentialCreationOptions
, ArrayBuffer
olan alanları içerdiğinden JSON.stringify()
tarafından desteklenmez. Bu, şu anda PublicKeyCredentialCreationOptions
öğesini HTTPS üzerinden göndermek için bazı alanların sunucuda base64URL
kullanılarak manuel olarak kodlanması ve ardından istemcide çözülmesi gerektiği anlamına gelir.
- Sunucuda, kodlama ve kod çözme işlemi genellikle FIDO sunucu tarafı kitaplığınız tarafından gerçekleştirilir.
- İstemcide, kodlama ve kod çözme işleminin şu anda manuel olarak yapılması gerekir. Gelecekte daha kolay hale gelecek: Seçenekleri JSON biçiminde
PublicKeyCredentialCreationOptions
biçimine dönüştürmek için bir yöntem kullanıma sunulacaktır. Chrome'daki uygulamanın durumuna göz atın.
Ö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ı işlemini generateRegistrationOptions
işlevine aktarıyoruz.
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://google-developers.gonglchuangl.net/identity/passkeys/developer-guides/server-registration/images/server-publicKeyCredentialCreationOptions.png?authuser=0&hl=tr)
navigator.credentials.create
, bir PublicKeyCredential
nesnesi döndürür.navigator.credentials.create
kodu istemcide başarıyla çözüldüğünde geçiş anahtarı başarıyla oluşturulmuş demektir. 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. Bu dosya, RP olarak daha sonra kullanıcının kimliğini doğrulamak için ihtiyaç duyacağınız yeni kimlik bilgileriyle ilgili bilgileri 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. Genellikle bu amaca yönelik bir yardımcı program işlevi sunar. SimpleWebAuthn teklifleri, örneğin, verifyRegistrationResponse
. Ek: Kayıt yanıtının doğrulanması bölümünden, arka planda gerçekleşen gelişmeler hakkında bilgi edinebilirsiniz.
Doğrulama başarılı olduğunda, kullanıcının daha sonra bu kimlik bilgisiyle 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 yalnızca tek bir şifresi olabilir, ancak birden fazla geçiş anahtarı olabilir (ör. Apple iCloud Anahtar Zinciri ile senkronize edilen bir geçiş anahtarı ve Google Şifre Yöneticisi aracılığıyla bir geçiş anahtarı).
Aşağıda, kimlik bilgisi 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ı bir kimliği. Bunu, Kullanıcılar tablonuz için birincil anahtar olarak kullanın.username
. Düzenlenebilir olabilecek, kullanıcı tanımlı kullanıcı adı.passkey_user_id
: Kayıt seçeneklerinizdeuser.id
ile temsil edilen, geçiş anahtarına özel, kimliği tanımlayabilecek bilgiler (PII) içermeyen kullanıcı kimliği. Daha sonra kullanıcı kimlik doğrulaması yapmaya çalıştığında, kimlik doğrulayıcı bupasskey_user_id
öğesiniuserHandle
içindeki kimlik doğrulama yanıtında kullanılabilir hale getirir.passkey_user_id
öğesini birincil anahtar olarak ayarlamamanızı öneririz. Birincil anahtarlar, yaygın olarak kullanıldıkları için sistemlerde fiili kimliği tanımlayabilecek bilgiler (PII) haline gelir.
- 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ı sağlayıcısı tarafından senkronize edilen geçiş anahtarları yedeklenir. İleridebacked_up
geçiş anahtarına sahip kullanıcıların şifrelerini kaydetmeyi düşünüyorsanız yedekleme durumunu saklamak yararlı olabilir.authenticatorData
ürünündeki işaretleri inceleyerek veya bu bilgilere kolayca erişmenizi sağlamak için genellikle mevcut olan FIDO sunucu tarafı kitaplık özelliğini kullanarak geçiş anahtarının yedeklenip yedeklenmediğini kontrol edebilirsiniz. Yedekleme uygunluğunun depolanması, olası kullanıcı sorgularının ele alınması açısından faydalı olabilir.name
: İsteğe bağlı olarak, kullanıcıların kimlik bilgilerine özel adlar vermesini sağlamak için kimlik bilgisinin görünen adı.transports
: Bir aktarım dizisi. Aktarımların depolanması, kimlik doğrulama kullanıcı deneyimi için kullanışlıdır. Aktarımlar kullanılabilir olduğunda tarayıcı buna göre 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, özellikleallowCredentials
alanının boş olmadığı yeniden kimlik doğrulama kullanım durumları için geçerlidir.
Geçiş anahtarı sağlayıcı, kimlik bilgisinin oluşturulma zamanı ve son kullanılma zamanı gibi diğer bilgileri de kullanıcı deneyimi amacıyla saklayabilirsiniz. Daha fazla bilgi için Geçiş anahtarları kullanıcı arayüzü tasarımı bölümünü inceleyin.
Örnek kod: kimlik bilgisini depolama
Örneklerimizde SimpleWebAuthn kitaplığını kullanıyoruz.
Burada, kayıt yanıtı doğrulamasını 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 { 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çeriyor:
response.clientDataJSON
, istemci verilerinin JSON sürümüdür. Web'deki veriler, tarayıcı tarafından görüldüğü şekildedir. RP kaynağını, görevi ve istemci bir Android uygulamasıysaandroidPackageName
içerir. Kısıtlanmış taraf olarakclientDataJSON
okuması,create
isteği sırasında tarayıcının gördüğü bilgilere erişmenizi sağlar.response.attestationObject
iki farklı bilgi içeriyor:attestationStatement
(onay kullanmazsanız sizinle alakalı değildir).authenticatorData
verileri, geçiş anahtarı sağlayıcısı tarafından görülüyor. Kısıtlanmış taraf olarak,authenticatorData
bu belgeyi okumak geçiş anahtarı sağlayıcısı tarafından görülen vecreate
isteği esnasında döndürülen verilere erişmenize olanak tanır.
authenticatorData
yeni oluşturulan geçiş anahtarıyla ilişkili ortak anahtar kimlik bilgisi hakkında önemli bilgileri içerir:
- Ortak anahtar kimlik bilgisinin kendisi ve benzersiz 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 burada olup olmadığı ve kullanıcının başarıyla doğrulanıp doğrulanmadığı (
userVerification
sayfasına göz atın). - Geçiş anahtarı sağlayıcıyı tanımlayan AAGUID. Geçiş anahtarı sağlayıcısının gösterilmesi, özellikle de birden fazla geçiş anahtarı sağlayıcıda hizmetiniz için kayıtlı geçiş anahtarı olan kullanıcılarınız için yararlı olabilir.
authenticatorData
, attestationObject
ile iç içe yerleştirilmiş olsa da onay kullanıp kullanmadığınıza bakılmaksızın geçiş anahtarı uygulamanız için içerdiği bilgiler gereklidir. authenticatorData
olarak 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 yapılan ayrıştırma ve kodu çözme konusunda bir miktar tasarruf etmek için getAuthenticatorData()
istemci tarafında yararlanabilirsiniz.
Ek: Kayıt yanıtının doğrulanması
Gelişmiş seçenekte, kayıt yanıtının doğrulanması aşağıdaki kontrollerden oluşur:
- Kısıtlanmış taraf 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ına ihtiyacınız varsa
authenticatorData.uv
kullanıcı doğrulama işaretinintrue
olduğundan emin olun. Geçiş anahtarları için kullanıcı varlığı her zaman gerekli olduğundanauthenticatorData.up
kullanıcı varlığı işaretinintrue
olduğundan emin olun. - İstemcinin, istediğiniz sorgulamayı sağlayıp sağlayamadığını kontrol edin. Onay kullanmazsanız bu kontrol önemli değildir. Ancak, bu kontrolün uygulanması 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.
- Kimlik bilgisini oluşturmak için geçiş anahtarı sağlayıcısı tarafından kullanılan algoritmanın, belirttiğiniz bir algoritma olduğunu doğrulayın (
publicKeyCredentialCreationOptions.pubKeyCredParams
öğesinin heralg
alanında, bu genellikle sunucu tarafı kitaplığınızda tanımlanır ve sizden görülemez). Bu, kullanıcıların yalnızca izin vermeyi seçtiğiniz algoritmalara kaydolmasını sağlar.
Daha fazla bilgi edinmek istiyorsanız SimpleWebAuthn'un verifyRegistrationResponse
için kaynak koduna bakın veya spesifikasyonda doğrulamaların tam listesini inceleyin.