19 Eylül 2025 Cuma

Web Uygulamana Passkey (WebAuthn) Ekleme: Node.js ile Şifresiz Giriş Rehberi 2025

Giriş

Şifresiz kimlik doğrulama, son yılların en önemli güvenlik dönüşümlerinden biri. Passkey (FIDO2/WebAuthn) sayesinde kullanıcılar, karmaşık şifrelerle uğraşmadan biyometri, güvenli donanım anahtarları veya cihaz kilidi ile giriş yapabiliyor. Bu rehberde, modern bir web uygulamasına Node.js ve tarayıcı WebAuthn API kullanarak passkey ekleme sürecini adım adım anlatıyorum. Odak noktamız: kolay kurulum, sağlam güvenlik ve güncel tarayıcı desteği.

Ön Koşullar

- Alan adınız ve HTTPS etkin (localhost için https://localhost da çalışır, ancak gerçek kullanıcılar için zorunlu HTTPS gereklidir).
- Node.js 18+ (WebCrypto ve fetch desteği için önerilir).
- Basit bir kullanıcı veritabanı (PostgreSQL, MongoDB ya da SQLite).
- Sunucu tarafında WebAuthn doğrulaması için bir kütüphane (örneğin simplewebauthn).
- RP ID (Relying Party ID) olarak genellikle kök alan adınız: example.com. Origin ise https://app.example.com gibi tam kaynak adresidir.

Mimari ve Akış

WebAuthn iki ana akıştan oluşur: Kayıt (Registration) ve Giriş (Authentication). Her ikisi de sunucunun ürettiği rastgele bir challenge değeriyle başlar.

1) Kayıt: Sunucu kullanıcıyı tanımlar, PublicKeyCredentialCreationOptions oluşturur ve challenge döner. Tarayıcı navigator.credentials.create() ile kullanıcıdan attestation üretir. Sunucu attestation’ı doğrular, credentialId ve publicKey gibi özet bilgileri veritabanına kaydeder.

2) Giriş: Sunucu PublicKeyCredentialRequestOptions döner. Tarayıcı navigator.credentials.get() ile assertion (imzalı kanıt) üretir. Sunucu imzayı ve sayaç değerini doğrular, oturumu açar.

Frontend: Kayıt Akışı

Kullanıcı giriş yaptıktan (veya e-posta doğruladıktan) sonra passkey kaydı başlatın. İstemci tarafında tipik istek:

const regOpts = await fetch('/webauthn/register/options').then(r => r.json());
const credential = await navigator.credentials.create({ publicKey: regOpts });
await fetch('/webauthn/register/verify', { method: 'POST', body: JSON.stringify(credential) });

SEO açısından önemli noktalar: “passkey kaydı”, “WebAuthn tarayıcı API”, “şifresiz kimlik doğrulama” gibi anahtar kelimeleri akışa doğal yerleştirin.

Backend: Kayıt Doğrulama

Sunucuda challenge değerini kullanıcıya özel ve tek kullanımlık olarak üretin. @simplewebauthn/server kullanıyorsanız generateRegistrationOptions ile seçenekleri üretir, verifyRegistrationResponse ile attestation doğrularsınız. Doğrulama sonrası şu alanları saklayın:

- credentialId: Kimlik.
- publicKey: İmza doğrulaması için gereken anahtar.
- signCount: Yeniden oynatma saldırılarına karşı sayaç.
- transports ve aaguid gibi meta bilgiler.

Frontend: Giriş (Authentication) Akışı

Kullanıcı giriş sayfasına geldiğinde, eğer passkey kayıtlıysa “Tek tıkla şifresiz giriş” sunabilirsiniz:

const authOpts = await fetch('/webauthn/auth/options?username=ali').then(r => r.json());
const assertion = await navigator.credentials.get({ publicKey: authOpts });
await fetch('/webauthn/auth/verify', { method: 'POST', body: JSON.stringify(assertion) });

Chrome’un Conditional UI özelliğiyle, kullanıcı adı alanına odaklanıldığında passkey önerisi otomatik çıkar. Bunun için mediation: 'conditional' kullanın ve sayfada autocomplete="username" bulunan bir alan bulundurun.

Güvenlik ve En İyi Uygulamalar

- Origin ve rpId kesin eşleşmeli. Ters proxy (Cloudflare, Nginx) arkası dağıtıma dikkat edin.
- Challenge benzersiz ve kısa ömürlü olsun; kullanıldıktan sonra silin.
- userVerification değerini tehdit modelinize göre belirleyin: required (yüksek güvenlik) veya preferred (daha iyi uyumluluk).
- residentKey (discoverable credentials) ile kullanıcı adı girmeden giriş deneyimi sağlayabilirsiniz. Bunun için residentKey: 'required' ve authenticatorSelection.requireResidentKey = true.
- Çoklu cihaz senkronizasyonu (iCloud Keychain, Google Password Manager) sayesinde passkey’ler cihazlar arasında taşınabilir; ancak kurumsal ortamda donanım güvenlik anahtarlarını (YubiKey vb.) zorunlu kılmak isteyebilirsiniz.

Test ve Hata Ayıklama

Chrome DevTools > More Tools > Virtual Authenticator ile fiziksel cihaz olmadan test yapabilirsiniz. Buradan platform/harici anahtar seçebilir, kullanıcı doğrulamasını simüle edebilirsiniz. Sık görülen hatalar: “Invalid RP ID” (alan adınız uyuşmuyor), “DOMException: The operation is insecure” (HTTPS yok), “Challenge mismatch” (eski veya farklı kullanıcıya ait challenge).

Veri Modeli ve Uyum

Bir kullanıcı birden fazla passkey’e sahip olabilir. Veritabanında users, credentials şeklinde ayrıştırın. Girişte birden çok allowCredentials döndürebilir veya discoverable credential ile boş gönderip tarayıcının seçmesini izleyebilirsiniz. KV veya bellek içi önbellek ile challenge yönetimini hızlandırın. KV kullansanız bile kalıcılık için veritabanına yedekleyin.

Dağıtım İpuçları

Sunucunuz HTTP/2 veya HTTP/3 arkasındaysa, Origin başlığının ve CF-Connecting-IP / X-Forwarded-Proto gibi başlıkların framework’ünüz tarafından doğru işlendiğinden emin olun. Serverless (Vercel, Cloudflare Workers) üzerinde de WebAuthn rahatlıkla çalışır; sadece rpId ve origin sabit ve tutarlı olmalı.

Sonuç

Passkey (WebAuthn) ile şifresiz kimlik doğrulama, hem güvenliği hem kullanıcı deneyimini ciddi biçimde iyileştiriyor. Node.js ve WebAuthn API sayesinde birkaç uç noktayı doğru kurgulayarak dakikalar içinde prototip çıkabilir, Conditional UI ile tek dokunuşla giriş deneyimi sunabilirsiniz. Doğru RP ID, benzersiz challenge yönetimi ve kapsamlı doğrulama kontrolleriyle, 2025’in güvenlik standartlarına uygun modern bir “şifresiz giriş” altyapısını bugün projelerinize ekleyin.

Hiç yorum yok: