Bu kılavuzda, kullanıcıların kayıtlı geçiş anahtarlarını görüntülemesine, yeniden adlandırmasına ve silmesine nasıl izin verileceği ayrıntılı olarak açıklanmaktadır. Bu sırada, kayıtlı kimlik bilgileri ve kullanıcı profili ayrıntıları, Signal API kullanılarak sunucu ile kullanıcının şifre yöneticileri arasında senkronize edilir.
Sunucu Tarafı İşlemler
Arka uç veritabanı katmanınız ve uç noktalarınız, kayıtlı kimlik bilgileri için yaygın CRUD işlemlerini ve kullanıcı profili ayrıntılarını güncellemeyi desteklemelidir. Çerçeveye özgü kitaplıklardan ayrılan sunucu, uç noktaları şunlara gösterir:
- Tüm kullanıcı kimlik bilgilerini listeleme: Oturum açmış kullanıcının kimliğiyle eşleşen tüm
StoredPasskeyCredentialkayıtlarını getirin. - Kimlik bilgisi adlarını güncelleme: Belirli bir kimlik bilgisi kimliği için yeni bir özel takma adı kabul edin ve güncellemeyi sunucuda kalıcı hale getirin.
- Kimlik bilgilerini silme: Belirli bir kimlik bilgisi kimliğini veritabanından kaldırın.
- Kullanıcı hesabı ayrıntılarını güncelleme: Oturum açmış kullanıcının profili için güncellenmiş
name(kullanıcı adı) vedisplayNamedeğerlerini kabul edin. Böylece istemci, bunları geçiş anahtarı sağlayıcısıyla senkronize edebilir.
// Node.js routing example for credential CRUD and user profile rename
router.get('/api/credentials', checkUserAuthenticated, async (req, res) => {
const list = await db.findCredentialsByUserId(req.user.id);
return res.json(list);
});
router.put('/api/credential/:id', checkUserAuthenticated, async (req, res) => {
const { id } = req.params;
const { name } = req.body;
const cred = await db.findCredentialById(id);
if (!cred || cred.passkeyUserId !== req.user.id) {
return res.status(404).json({ error: 'Credential not found.' });
}
cred.name = name;
await db.saveCredential(cred);
return res.json(cred);
});
router.delete('/api/credential/:id', checkUserAuthenticated, async (req, res) => {
const { id } = req.params;
const cred = await db.findCredentialById(id);
if (!cred || cred.passkeyUserId !== req.user.id) {
return res.status(404).json({ error: 'Credential not found.' });
}
await db.deleteCredential(id);
return res.json({ success: true });
});
router.put('/api/user', checkUserAuthenticated, async (req, res) => {
const { name, displayName } = req.body;
const updatedUser = await db.updateUser(req.user.id, { name, displayName });
return res.json(updatedUser);
});
İstemci Tarafı Yönetim Kullanıcı Arayüzü
Kullanıcıların kayıtlı kimlik doğrulama seçeneklerini ve hesap profili ayrıntılarını kolayca denetleyip yönetebileceği özel bir ayarlar paneli oluşturun:
- Kayıtlı listeyi göster: Listeyi uç noktanızdan alın ve her bir kimlik bilgisi satırını oluşturun. Yanıt boşsa faydalı bir boş durum mesajı (ör. "Geçiş anahtarı bulunamadı") oluşturun.
- AAGUID meta verilerini eşleme: Her geçiş anahtarının sağlayıcı ayrıntılarını oluşturmak için yerel kayıt defterinizde
aaguidözelliğini arayın. Daha fazla bilgi için AAGUID'den geçiş anahtarı sağlayıcısını belirleme bölümüne bakın. - Öğe Başına Kullanıcı Arayüzü Şartları: Liste kapsayıcısındaki her satır şunları oluşturmalıdır:
- Sağlayıcı simgesi: AAGUID'den türetilen resim veya veri URI'si.
- Sağlayıcı/Özel Ad: AAGUID'den türetilen ad veya kullanıcı tarafından yeniden adlandırılan dize.
- Kayıt Tarihi: Veritabanında saklanan ham zaman damgası
registeredAt, istemci ekranında okunabilir bir tarih biçimine dönüştürülür. - Son Kullanım Tarihi: Veritabanında saklanan ham epoch zaman damgası
lastUsedAt, istemci ekranı için okunabilir bir tarihe (varsa) biçimlendirilir. - Yeniden Adlandır Düğmesi: Sunucudaki (
PUT /api/credential/:id) kimlik bilgisinin özel takma adını güncellemek için yeniden adlandırma işlemini tetikler. Not: Tek bir geçiş anahtarının takma adını yeniden adlandırmak, sunucu tarafında bir etiket değişikliğidir vesignalCurrentUserDetails()'yi çağırmaz. - Sil düğmesi: Kimlik bilgisinin (
DELETE /api/credential/:id) silinmesini tetikler ve kalan kimlik bilgilerinisignalAllAcceptedCredentials()üzerinden senkronize eder.
- Kullanıcı Hesabı Yeniden Adlandırma Kullanıcı Arayüzü:
- Kullanıcının hesap kullanıcı adını (
name) veyadisplayName(PUT /api/user) güncellemesine olanak tanıyan bir kontrol sağlayın ve güncellenen kullanıcı ayrıntılarınıPublicKeyCredential.signalCurrentUserDetails()aracılığıyla şifre yöneticisiyle hemen senkronize edin.
- Kullanıcının hesap kullanıcı adını (
- Koşullu "Geçiş Anahtarı Oluştur" düğmesi:
- Yönetim sayfasında belirgin bir "Geçiş anahtarı oluştur" kayıt tetikleyici düğmesi sunun. Bu kullanıcı arayüzü öğesini oluşturmadan önce sayfa, platform kimlik doğrulayıcının desteklendiğini doğrulamak için
PublicKeyCredential.getClientCapabilities()kullanarak özellikleri algılamalıdır. Geçiş anahtarları desteklenmiyorsa bu düğmeyi gizleyin ve kullanıcıları standart çok faktörlü kimlik doğrulama kayıtlarına yönlendirin. navigator.credentials.create()çağrısındaauthenticatorSelection.authenticatorAttachmentatlanarak güvenlik anahtarı kaydedilmesine izin ver.
- Yönetim sayfasında belirgin bir "Geçiş anahtarı oluştur" kayıt tetikleyici düğmesi sunun. Bu kullanıcı arayüzü öğesini oluşturmadan önce sayfa, platform kimlik doğrulayıcının desteklendiğini doğrulamak için
Signal API Senkronizasyonu
Signal API, uygulamanın kimlik bilgisi durumlarını şifre yöneticilerine iletmesine olanak tanır. Böylece kullanıcının senkronize edilmiş kasaları ve arka uç veritabanınız senkronize edilir.
- Özellik Algılama ve Parametre Kodlama Kuralı:
- Signal API yöntemlerini çağırmadan önce her zaman özellik algılama yapın (
if (PublicKeyCredential.signalAllAcceptedCredentials)veif (PublicKeyCredential.signalCurrentUserDetails)). - Signal API yöntemlerine (
signalAllAcceptedCredentials,signalCurrentUserDetails) iletilen tümuserIdve kimlik bilgisi kimliği parametreleri Base64URL kodlamalı dizeler OLMALIDIR.
- Signal API yöntemlerini çağırmadan önce her zaman özellik algılama yapın (
- Sayfa yükleme senkronizasyonunu başlatma:
- Uygulama, yönetim sayfası yüklendiğinde
signalAllAcceptedCredentials()yöntemini otomatik olarak çağırmalıdır (örneğin, birDOMContentLoadedetkinlik işleyici, modül başlatma veyauseEffectgibi bir çerçeve bileşeni bağlama kancası içinde).
- Uygulama, yönetim sayfası yüklendiğinde
- Yönetim Güncellemeleri Senkronizasyonu:
- Uygulama, kimlik bilgisi silme tıklama işleyicinizde getirme işleminden hemen sonra
signalAllAcceptedCredentials()yöntemini çağırmalıdır. - Uygulama, kullanıcı hesabınızı yeniden adlandırma (
nameveyadisplayName) tıklama işleyicisi getirme işleminden hemen sonrasignalCurrentUserDetails()yöntemini çağırmalıdır.
- Uygulama, kimlik bilgisi silme tıklama işleyicinizde getirme işleminden hemen sonra
// Client-side management synchronization ES module
import { listFetch, renameCredentialFetch, updateUserFetch, deleteFetch } from './api.js';
// Base64URL-encoded User ID string (illustration only)
const base64UrlUserId = "M2YPl-KGnA8";
async function syncAcceptedCredentials(currentCredentialsList) {
if (!window.PublicKeyCredential || !PublicKeyCredential.signalAllAcceptedCredentials) return;
try {
const credentialIds = currentCredentialsList.map(c => c.id); // Array of Base64URL credential ID strings
await PublicKeyCredential.signalAllAcceptedCredentials({
rpId, // RP ID must match the one defined on the server
userId: base64UrlUserId, // User ID Base64URL-encoded string
allAcceptedCredentialIds: credentialIds
});
} catch (e) {
console.error('SignalAllAcceptedCredentials sync failure:', e);
}
}
async function loadManagementPanel() {
const response = await listFetch();
const list = await response.json();
renderUI(list);
// Sync accepted credentials on initial load
await syncAcceptedCredentials(list);
}
async function performDelete(credentialId) {
const response = await deleteFetch(credentialId);
if (response.ok) {
const updatedResponse = await listFetch();
const updatedList = await updatedResponse.json();
renderUI(updatedList);
// Sync remaining accepted credentials after deletion
await syncAcceptedCredentials(updatedList);
}
}
// Renaming a passkey's nickname updates the server record only
async function performCredentialRename(credentialId, newCredentialName) {
const response = await renameCredentialFetch(credentialId, { name: newCredentialName });
if (response.ok) {
const updatedResponse = await listFetch();
renderUI(await updatedResponse.json());
}
}
// Renaming the user's account username or displayName triggers signalCurrentUserDetails
async function performUserRename(rpId, userId, updatedName, updatedDisplayName) {
const response = await updateUserFetch({ name: updatedName, displayName: updatedDisplayName });
if (response.ok && window.PublicKeyCredential && PublicKeyCredential.signalCurrentUserDetails) {
try {
await PublicKeyCredential.signalCurrentUserDetails({
rpId, // RP ID must match the one defined on the server
userId, // Base64URL-encoded user ID
name: updatedName, // Updated username
displayName: updatedDisplayName // Updated display name
});
} catch (e) {
console.error('SignalCurrentUserDetails sync failure:', e);
}
}
}
window.addEventListener('DOMContentLoaded', loadManagementPanel);
AAGUID'den geçiş anahtarı sağlayıcısını belirleme
AAGUID (Kimlik Doğrulayıcı Onayı Küresel Benzersiz Tanımlayıcısı), belirli bir örneği değil, kimlik doğrulayıcının modelini temsil eden 128 bitlik bir tanımlayıcıdır. Geçiş anahtarı kaydı sırasında kimlik doğrulayıcı verilerine dahil edilir ve hangi geçiş anahtarı sağlayıcısının (ör. Google Şifre Yöneticisi, iCloud Anahtar Zinciri, 1Password) kimlik bilgisi oluşturduğunu belirlemek için kullanılabilir.
AAGUID yalnızca kullanıcılara geçiş anahtarı yönetiminde yardımcı olmak için kullanılmalıdır. Kriptografik olarak onaylanmadığı sürece değiştirilebilir. Platform geçiş anahtarları şu anda bunu desteklemez.
1. AAGUID Kayıt Defteri
AAGUID'lerin sağlayıcı adları ve simgeleriyle topluluk tarafından yönetilen JSON eşlemesi şu adreste bulunabilir:
https://raw.githubusercontent.com/passkeydeveloper/passkey-authenticator-aaguids/refs/heads/main/combined_aaguid.json
Her giriş aşağıdaki şemaya sahiptir:
{
"<aaguid-uuid>": {
"name": "Provider Name",
"icon_light": "data:image/png;base64,...",
"icon_dark": "data:image/png;base64,..."
}
}
2. Kayıttan sonra AAGUID'yi kullanma
Kayıt yanıtını doğruladıktan sonra kayıt sonucundaki aaguid değerini okuyun ve kimlik bilgisinin name ve providerIcon değerlerini doldurmak için kayıt defterinde arayın:
Kayıt defterinde AAGUID'yi aramadan önce '00000000-0000-0000-0000-000000000000' değerine eşit olup olmadığını kontrol edin. Bu durumda, kayıt defteri aramasını atlayın ve name değerini bir yedek (ör. kullanıcı aracısından alınan cihaz adı veya "Bilinmeyen geçiş anahtarı sağlayıcı") ve providerIcon değerini undefined olarak ayarlayın. Yalnızca sıfırlanmamış AAGUID'ler için kayıt defterine bakın.
import aaguids from './aaguids.json' with { type: 'json' };
const { aaguid } = registrationInfo;
if (aaguid === '00000000-0000-0000-0000-000000000000') {
// use the device name as the passkey provider based on
// the information derived from the user agent string,
// or just say "Unknown passkey provider"
} else {
const provider = aaguids[aaguid];
const credential = {
// ...other fields
aaguid,
name: provider?.name || 'Unknown passkey provider',
providerIcon: provider?.icon_light,
};
}
Yedek Stratejiler
Geçiş anahtarı özelliği algılama yedeği
"webauthn-polyfills"i her zaman yükleyin ve bağlama aktarın.
PublicKeyCredential desteklendiği sürece PublicKeyCredential.getClientCapabilities de desteklenir.
import 'webauthn-polyfills';
Signal API Senkronizasyonu Yedeklemesi
Tarayıcı PublicKeyCredential.parseRequestOptionsFromJSON özelliğini desteklemiyorsa "webauthn-polyfills" kullanın:
<script type="module">
if (!PublicKeyCredential.parseRequestOptionsFromJSON) {
await import('https://unpkg.com/webauthn-polyfills');
}
</script>
Bu işlem, PublicKeyCredential.prototype.toJSON için de destek ekler.