7 Kasım 2025 Cuma

Passkeys (WebAuthn) ile Şifresiz Giriş: Next.js ve Node.js Üzerinde Adım Adım

Passkeys nedir ve neden şimdi?

Şifre yorgunluğu, kimlik avı ve parola sızıntıları artık sıradan hale geldi. Passkeys, yani WebAuthn ve FIDO2 tabanlı şifresiz kimlik doğrulama, bu sorunları kökten çözen modern bir yaklaşım. Apple, Google ve Microsoft ekosistemlerinde yerleşik çalışırken, kullanıcılar cihazlarının biyometrisini (Face ID, Touch ID, Windows Hello) veya güvenlik anahtarlarını kullanarak güvenli ve tek dokunuşla giriş yapabiliyor. Bu yazıda, Next.js ve Node.js üzerinde Passkeys entegrasyonunu adım adım anlatacağım.

Mimari ve çalışma mantığı

Passkeys, asimetrik kriptoya dayanır: cihaz üzerinde üretilen bir özel anahtar ve sunucuda saklanan açık anahtar. Kayıt (registration) sırasında cihaz, alan adınıza (RP ID) bağlı bir anahtar çifti üretir ve attestation ile birlikte sunucuya gönderir. Giriş (authentication) aşamasında ise sunucu bir challenge üretir; cihaz bu challenge’ı özel anahtarla imzalar ve sunucu açık anahtarla doğrular. Şifre yok, gizli veri sunucuya taşınmıyor ve kimlik avına dayanıklı bir akış elde ediliyor.

Önkoşullar

1) Üretimde mutlaka HTTPS kullanın.
2) RP ID, alan adınızla birebir uyumlu olmalı (örn. example.com).
3) Tarayıcı desteği: Modern Chrome, Safari, Firefox sürümleri WebAuthn destekliyor.
4) En az bir authenticator (platform: telefon/bilgisayar; roaming: YubiKey).
5) Node.js 18+ ve Next.js 13+ önerilir.
6) Sunucuda rastgele ve tekil challenge üretecek bir mekanizma (ör. crypto.randomBytes) ve doğrulama için bir kütüphane (örn. @simplewebauthn/server) kullanın.

Kayıt (Registration) akışı

1. Kullanıcıyı başlatın: Kullanıcı e-postası veya kullanıcı adıyla kayıt talebi gönderir.
2. Sunucu challenge üretir: RP bilgileriyle birlikte options döner: rp.id, rp.name, user.id (stabil benzersiz ID), user.name, pubKeyCredParams, attestation, timeout.
3. İstemci oluşturma isteği: Tarayıcıda navigator.credentials.create({ publicKey: options }) çağrısı yapılır.
4. Sunucu doğrular: İstemciden gelen attestation yanıtı (id, rawId, response.attestationObject, clientDataJSON) sunucuda doğrulanır. Başarılıysa credentialId, publicKey, signCount ve kullanıcıyla ilişkilendirilerek veritabanına kaydedilir.

Örnek sunucu mantığı (özet):
// /api/webauthn/register/options
const options = generateRegistrationOptions({ rpID, rpName, userID, userName });
storeChallenge(userID, options.challenge);
return options;

// /api/webauthn/register/verify
const verification = verifyRegistrationResponse({ response, expectedRPID: rpID, expectedOrigin, expectedChallenge });
if (verification.verified) saveCredential(userID, verification.registrationInfo);

Giriş (Authentication) akışı

1. Sunucu assertion options üretir: registered credentialId’leri, rpID ve challenge içeren options döndürür.
2. İstemci doğrulama isteği: navigator.credentials.get({ publicKey: options }) çağrısı çalışır. Kullanıcı biyometri/güvenlik anahtarıyla onay verir.
3. Sunucu doğrular: İmza (signature), authenticatorData ve clientDataJSON kullanılarak open-key üzerinde imza doğrulanır.
4. Sayaç kontrolü: authenticator signCount önceki değerden küçükse tekrar saldırısı şüphesi doğar; oturumu reddedin. Başarılıysa kullanıcıyı oturum açmış sayın.

Örnek sunucu mantığı (özet):
// /api/webauthn/login/options
const options = generateAuthenticationOptions({ rpID, allowCredentials: userCredIds });
storeChallenge(userID, options.challenge);
return options;

// /api/webauthn/login/verify
const verification = verifyAuthenticationResponse({ response, expectedRPID: rpID, expectedOrigin, expectedChallenge, authenticator });
if (verification.verified) updateSignCount(authenticator, verification.authenticationInfo.newCounter);

Next.js tarafında istemci akışı

Next.js App Router ile, client component içinde WebAuthn çağrılarını başlatabilirsiniz. Kayıtta: sunucudan options’ı fetch edin, navigator.credentials.create ile yanıtı alın ve verify endpoint’ine POST edin. Girişte: benzer şekilde options alıp navigator.credentials.get çağırın. Hata yönetimi için kullanıcıya net mesajlar gösterin (ör. “Bu cihazda passkey yok, lütfen yeni bir passkey oluşturun”).

Güvenlik ve en iyi uygulamalar

- Origin ve RP ID uyuşmazlıklarını önleyin; staging/prod için ayrı ayar kullanın.
- Challenge değerleri kriptografik rastgele ve tek kullanımlık olmalı.
- Attestation politikasını belirleyin: “none”, “indirect” veya belirli üretici politikaları.
- Çoklu cihaz desteği için bir kullanıcıya birden fazla credential bağlayın.
- Yedekleme/kurtarma senaryosu için platform passkey + güvenlik anahtarı kombinasyonunu teşvik edin.
- Oturum çerezi/Token için HttpOnly, Secure ve SameSite ayarlarını doğru yapılandırın.

Kullanıcı deneyimi ipuçları

- Conditional UI (Chrome) ile otomatik Passkey doldurma akışını etkinleştirin; login sayfasında kullanıcı adı sormadan hızlı giriş sunar.
- Parolayı gizli seçenek olarak sunun; öncelik Passkey akışında olsun.
- Kullanıcıya “Bu cihazda passkey oluştur” veya “Farklı cihazla tara” gibi net eylemler verin.
- Mobilde QR tabanlı çapraz cihaz akışlarını destekleyin; tarayıcılar yerleşik olarak buna hazır.

Performans ve gözlemleme

WebAuthn işlemleri genellikle milisaniyeler içinde biter, ancak ağ gecikmesi ve attestation doğrulaması süresini izleyin. Kayıt ve giriş sürelerini ölçmek için basit metrikler (options fetch süresi, create/get süresi, verify süresi) tutun. Başarısızlık oranlarını izlemek, cihaz/OS bazlı hataları hızlıca ayrıştırmanızı sağlar.

Sonuç

Passkeys, güvenliği artırırken kullanıcı deneyimini de iyileştirir. Next.js ve Node.js üzerinde WebAuthn/FIDO2 ile kuracağınız şifresiz giriş çözümü, kimlik avına dirençli, hızlı ve modern bir oturum açma deneyimi sunar. Yukarıdaki mimari ve akışla kısa sürede üretim seviyesinde bir entegrasyon geliştirebilir, parolalara veda ederken dönüşüm oranlarınızı artırabilirsiniz.

Hiç yorum yok: