Uygulamanızın kabul ettiği her parola tahmin edilebilir, başka bir sitede yeniden kullanılabilir, sahte bir giriş sayfasına yazılabilir veya bir veritabanı yedeğinden sızdırılabilir. Passkey'ler bu dört sorunu birden ortadan kaldırır. Kullanıcı, telefonu veya dizüstü bilgisayarı zaten kilidini açan parmak izi, yüz veya PIN ile oturum açar ve sunucunuzda çalmaya değer bir sır kalmaz.
Yeni giriş bileşenlerine genel bakış yazısında passkey'ler yalnızca beş madde aldı, SAML yazısı ise kendi identity provider'ını işleten şirketler için oturum açmayı ele aldı. Bu yazı parolasız tarafı anlatıyor: TsgcWSAPIServer_WebAuthn passkey'leri nasıl kaydeder, kullanıcıları kullanıcı adı olmadan nasıl oturum açtırır, passkey'leri tarayıcının otomatik doldurma listesinde nasıl gösterir ve her credential'ı kendi veritabanınızda nasıl saklar.
Passkey Nedir
Passkey, kullanıcının authenticator'ı tarafından oluşturulan bir anahtar çiftidir: Windows Hello, iCloud Anahtar Zinciri, Google Şifre Yöneticisi, bir parola yöneticisi veya bir FIDO2 güvenlik anahtarı. Özel anahtar hiçbir zaman authenticator'dan çıkmaz. Sunucunuz yalnızca genel anahtarı saklar, bu yüzden sızdırılan bir passkey tablosu kimsenin oturum açmasına izin vermez. Her imza sitenizin domainine bağlıdır, bu yüzden benzer görünümlü bir oltalama domaini kullanabileceği hiçbir şey elde edemez. Burada kimlik avına dayanıklı ifadesinin anlamı budur.
WebAuthn terimleriyle bir passkey, keşfedilebilir bir credentialdir, resident key olarak da adlandırılır. Authenticator, userHandle'ı özel anahtarın yanında tutar; bu yüzden kullanıcı bir kullanıcı adı yazmadan oturum açabilir ve tarayıcı sitenizin passkey'lerini kendi başına listeleyebilir.
Keşfedilebilir Credential'lar İsteme
WebAuthn güvenli bir bağlam gerektirir, bu yüzden sayfalarınızı https üzerinden, geliştirme sırasında ise localhost'tan sunun ve WebAuthnOptions.RelyingParty değerini tarayıcının gösterdiği host adına ayarlayın. Kayıt seçeneklerinin istediği residentKey, WebAuthnOptions.DefaultOptions.Registration.DiscoverableCredential değerinden gelir:
waundcPreferred, varsayılan değer. Authenticator, mümkün olduğunda keşfedilebilir bir credential oluşturur.waundcRequired. Yalnızca keşfedilebilir credential'lar kabul edilir. Passkey'ler ve kullanıcı adı olmadan oturum açma için kullanın.waundcDiscouraged. Authenticator, oturum açmak için kullanıcı adı gerektiren sunucu tarafı bir credential oluşturmalıdır.
Tek bir kayıt isteği, discoverable_credential alanını required, preferred veya discouraged olarak ayarlayarak varsayılan değeri yine de geçersiz kılabilir.
Kullanıcı Adı Olmadan Oturum Açma
Kimlik doğrulama seçeneklerini boş bir kullanıcı adıyla isteyin. Bu durumda seçenekler herhangi bir allowCredentials listesi taşımaz, tarayıcı relying party'niz için sahip olduğu passkey'leri gösterir ve kullanıcı bunlardan birini seçer. Yazılacak hiçbir şey olmadığından yanlış yazılacak hiçbir şey de yoktur.
Bu kez credential'ı sunucu seçmediği için daha fazla kontrol yapar. Yanıt userHandle'ı içermelidir, userHandle imzalayan credential'a ait olmalıdır ve uygulamanızın tanımadığı bir credential reddedilir.
Otomatik Doldurma Listesindeki Passkey'ler
Otomatik doldurma, yani conditional mediation, sitenizin passkey'lerini kayıtlı parolaların yanında kullanıcı adı alanının öneri listesine yerleştirir. Bu, kullanıcıları geçirmenin yumuşak yoludur: giriş sayfası parolası olan kişiler için çalışmaya devam eder, passkey'i olan kişiler ise listeden seçer.
- Kullanıcı adı alanına
autocomplete="username webauthn"ekleyin. - Sayfada
/sgcWebAuthn.jsdosyasını yükleyin. Bileşen bunuEndpointsOptions.WebAuthniçinde ayarlanan uç noktadan kendisi sunar. - Sayfa yüklendiğinde kullanıcı adsız seçenekleri isteyin ve
startAuthentication(options, true)çağrısını yapın. Kullanıcı listeden bir passkey seçtiğinde promise çözülür.
Otomatik doldurma, conditional mediation'ı destekleyen bir tarayıcı gerektirir; bu da bugün için Chrome, Edge ve Safari'nin güncel sürümleri anlamına gelir. browserSupportsWebAuthnAutofill() diğerlerinde False döndürür, bu yüzden sayfada ayrıca bir “Passkey ile giriş yap” düğmesi de bulundurun.
Birden Çok Passkey, Tek Bir userHandle
Gerçek kullanıcıların birden fazla passkey'i vardır: dizüstü bilgisayarda biri, telefonda biri, belki ikisinin de kaybolduğu gün için bir güvenlik anahtarı. Her birini aynı kullanıcı adıyla kaydedin. Bu kullanıcı adının sunucunun zaten bildiği credential'ları varsa, yeni kayıt onların userHandle'ını (user.id) yeniden kullanır, böylece hesabın her passkey'i tek bir userHandle'ı paylaşır ve hepsi aynı kullanıcıya götürür.
Sunucu, çalışırken kaydedilen credential'ları ve AddCredential ile eklediklerinizi bilir. Passkey'leriniz bir veritabanında yaşıyorsa, her hesabın tek bir userHandle'ı korumasını sağlamak için bunları başlangıçta ekleyin. Bir kullanıcı gerçekten bir kullanıcı adı yazdığında, kimlik doğrulama seçenekleri o kullanıcının her passkey'ini allowCredentials içinde listeler ve authenticator elindekini kullanır.
Passkey'leri Kendi Veritabanınızda Saklayın
Bileşen credential'ları kalıcı hale getirmez. Passkey'leriniz kullanıcılar tablonuzun yanında yer alır ve dört olay ikisini birbirine bağlar:
OnWebAuthnRegistrationSuccessful. Yeni credential kaydını, örneğinaCredentialRecord.AsJSON,CredentialIdveUsernamedeğerleriyle birlikte kaydedin.OnWebAuthnAuthenticationOptionsRequest. Bir kullanıcı adı varsa, o kullanıcının passkey'leriniCredentialRecordsiçine ekleyin. Kullanıcı adı yoksa hiçbir şey eklemeyin.OnWebAuthnAuthenticationGetCredential. Tarayıcının seçtiği credential, bu ceremony'nin listesinde yoksa tetiklenir; bu, her kullanıcı adsız ve otomatik doldurmalı oturum açmada geçerlidir. Credential'ı arayın,aCredentialRecordiçini doldurun veFounddeğerini ayarlayın.OnWebAuthnAuthenticationSuccessful.aAuthentication.Credential.CredentialRecord'un yeniSignCountveBackupStatedeğerlerini kaydedin, ardından oturumu oluşturun.
Bir passkey'i kaydetmek ve geri yüklemek iki kısa handler'dan oluşur:
uses
sgcWebAuthn_Classes;
// registration: store the whole record, keyed by its credential id
procedure TForm1.WebAuthnWebAuthnRegistrationSuccessful(Sender: TObject;
const aRegistration: TsgcWebAuthn_Registration;
const aCredentialRecord: TsgcWebAuthn_CredentialRecord; var Accept: Boolean);
begin
DBInsertPasskey(aCredentialRecord.CredentialId, aCredentialRecord.Username,
aCredentialRecord.AsJSON);
end;
// usernameless and autofill sign-in: the browser chose the passkey,
// find it by its credential id and hand it back to the server
procedure TForm1.WebAuthnWebAuthnAuthenticationGetCredential(Sender: TObject;
const aCredentialId: string;
const aCredentialRecord: TsgcWebAuthn_CredentialRecord; var Found: Boolean);
var
vJSON: string;
begin
Found := DBFindPasskey(aCredentialId, vJSON);
if Found then
aCredentialRecord.ReadJSON(vJSON);
end;
DBInsertPasskey ve DBFindPasskey, kendi veri erişim kodunuzu temsil eder. Döndürdüğünüz kayıt istenen CredentialId'yi ve ceremony bir kullanıcı adıyla başladıysa aynı Username'i taşımalıdır, aksi halde oturum açma başarısız olur. Sunucu, authenticator'ın gönderdiği userHandle ile karşılaştırdığından, saklanan kayıtta UserId'yi de tutun. Olaylar sunucunun bağlantı thread'lerinde çalışır, bu yüzden paylaşılan kaynakları sunucunun başka herhangi bir yerinde koruduğunuz gibi koruyun.
Senkronize mi, Cihaza Bağlı mı
Authenticator verisindeki bayraklar aldığınız passkey türünü söyler; credential kaydı bunları BackupEligible (BE bayrağı) ve BackupState (BS bayrağı) olarak saklar:
- BackupEligible True, BackupState True. Platform veya parola yöneticisi tarafından yedeklenen ve kullanıcının diğer cihazlarında da kullanılabilen senkronize bir passkey.
- BackupEligible True, BackupState False. Henüz yedeklenmemiş, çoklu cihaz destekli bir passkey.
- BackupEligible False, BackupState False. Bir güvenlik anahtarı veya cihazı hiç terk etmeyen bir TPM anahtarı gibi, cihaza bağlı bir passkey. Kullanıcıya ikinci bir passkey kaydetmesini önerin, çünkü o cihazı kaybetmek credential'ı kaybetmek anlamına gelir.
Politikanız bunlara farklı davranabilir, örneğin yönetici hesaplarında yalnızca cihaza bağlı güvenlik anahtarlarını kabul edebilir. Her oturum açmada sunucu, BS bayrağı ayarlanmış ve BE bayrağı ayarlanmamış bir yanıtı reddeder; ayrıca BE bayrağı saklanan BackupEligible değerinden farklı olan bir yanıtı da reddeder, çünkü bir credential'ın eligibility'si hiçbir zaman değişmez. Yeni BS bayrağı BackupState'e kopyalanır ve bunu kaydedeceğiniz yer OnWebAuthnAuthenticationSuccessful'dır.
İmza Sayacı ve Klonlanmış Authenticator'lar
Bazı authenticator'lar her oturum açmada bir imza sayacını artırır. Yanıttaki sayaç veya saklanan SignCount sıfır değilse, yanıttaki sayaç saklanan değerden büyük olmalıdır. Değilse oturum açma reddedilir, çünkü aynı anahtarla yanıt veren iki authenticator, tam olarak klonlanmış bir authenticator'ın görünümüdür.
Bu kontrol yalnızca sayacı her oturum açmadan sonra kaydederseniz ve saklanan değer yalnızca ileri doğru ilerlerse çalışır. Senkronize passkey'ler genellikle her seferinde 0 bildirir, bu da onlar için kontrolü devre dışı bırakır. Sayacı güvenilir biçimde artırmayan authenticator'larınız varsa, onları kabul etmek için WebAuthnOptions.AllowSignCountLessOrEqualStoredValue değerini True olarak ayarlayın. Saklanan değer yine de asla düşürülmez.
Demoyu Deneyin
Demo Demos\26.Authentication\01.Passkeys, eksiksiz bir relying party'dir: TsgcWSAPIServer_WebAuthn bağlı bir TsgcWebSocketHTTPServer, https://localhost:5443 üzerinde küçük bir giriş sayfası sunar. Yukarıdaki dört olay aracılığıyla her passkey'i kendi passkeys.json dosyasında saklar.
- Demoyu derleyin ve libcrypto-3.dll ile libssl-3.dll dosyalarını çalıştırılabilir dosyanın yanında tutun. Bunlar demo klasöründe bulunur.
- Host'u 127.0.0.1, portu 5443 ve relying party'yi localhost olarak bırakın, ardından Start'a tıklayın.
- Open Browser'a tıklayın ve kendinden imzalı test sertifikasını kabul edin.
- Bir kullanıcı adı yazın ve Register passkey'e tıklayın. Aynı kullanıcı adı için ikinci bir passkey kaydedin. Form, her passkey'i türüyle (senkronize veya cihaza bağlı) ve imza sayacıyla birlikte listeler.
- Sign in without user name'a tıklayın ve bir passkey seçin. Sunucu onu
OnWebAuthnAuthenticationGetCredentialaracılığıyla bulur ve günlük kullanıcıyı gösterir. - Sayfayı yeniden yükleyin ve kullanıcı adı kutusuna tıklayın. Passkey'ler otomatik doldurma listesinde görünür. Oturum açmak için birini seçin.
- Uygulamayı yeniden başlatın. Passkey'ler passkeys.json dosyasından yeniden yüklenir; bu da depolamanın bileşene değil uygulamanıza ait olduğunu gösterir.
Belgeler
Nereden Edinilir
TsgcWSAPIServer_WebAuthn, Delphi ve C++ Builder için sgcWebSockets'in Enterprise ve All-Access sürümlerinde bulunur ve aynı bileşen sgcWebSockets .NET'in de bir parçasıdır. Yalnızca kimlik doğrulamaya ihtiyacınız varsa, sgcAuth paketi onu diğer giriş bileşenleriyle birlikte içerir. SGC Auth paletinde bulabilirsiniz ve bir forma sürükleyene kadar mevcut bir uygulamada hiçbir şey değişmez.
Sırada Ne Var
- Passkeys, SAML SSO, LDAP ve TOTP 2FA ile Delphi'de Giriş
- Entra ID, Okta ve AD FS ile Delphi'de SAML Tekli Oturum Açma
- WebAuthn, Passkeys ve Parolaların Sonu
İzleyin
eSeGeCe kanalında “Passkeys in Delphi: passwordless login with WebAuthn” başlıklı kısa bir video var. Video, IDE'deki kodu, yedekleme bayraklarının ve imza sayacının size neler anlattığını ve https://localhost üzerinde çalışan demoyu gösteriyor: bir kullanıcı iki passkey kaydediyor, ardından bir kullanıcı adı yazmadan oturum açıyor.
Sorularınız mı var, geri bildiriminiz mi var, yoksa giriş sayfanıza passkey eklemek için yardıma mı ihtiyacınız var? Bize ulaşın. Kodu yazan kişilerden yanıt alacaksınız.
