parolasız kimlik doğrulama etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
parolasız kimlik doğrulama etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

2 Aralık 2025 Salı

Passkey (WebAuthn/FIDO2) ile Parolasız Giriş: Next.js Üzerinde Adım Adım Kurulum

Passkey nedir ve neden önemlidir?

Parolasız kimlik doğrulama, son yılların en önemli güvenlik trendlerinden biri. Passkey teknolojisi (WebAuthn/FIDO2), kimlik doğrulamayı klasik parolaların ötesine taşıyarak kimlik avına dayanıklı ve kullanıcı dostu bir deneyim sunuyor. Apple, Google ve Microsoft’un ekosistemleriyle entegre çalışan passkey’ler; cihazdaki güvenli donanım veya güvenli alanı kullanarak anahtar çifti üretir ve web sitelerine girişte yalnızca özel anahtar cihazda kalır. Böylece kullanıcılar Touch ID/Face ID, Windows Hello veya Android’in biyometrik yöntemleriyle tek dokunuşla güvenli giriş yapabilir.

Nasıl çalışır? (Kısa teknik özet)

Passkey, tarayıcıların sunduğu WebAuthn API üzerinden etkileşim kurar. Site (Relying Party), kayıt sırasında tarayıcıya bir “challenge” ve alan adı (rpID) gönderir. Kullanıcının cihazı bir anahtar çifti üretir; genel anahtar sunucuya kaydedilir, özel anahtar cihazda kalır. Giriş esnasında sunucu yeni bir “challenge” üretir; cihaz bu “challenge”ı özel anahtarla imzalar ve sunucu imzayı doğrular. Bu yapı sayesinde şifre sızması, parola doldurma saldırıları ve kimlik avı riskleri önemli ölçüde azalır.

Önkoşullar ve mimari

Bu rehberde Next.js 14 (App Router) üzerinde örnek bir passkey akışı kuracağız. İhtiyacınız olanlar: Node.js 18+, Next.js projesi, HTTPS (geliştirirken localhost desteklenir), bir veritabanı (ör. PostgreSQL, MongoDB) ve WebAuthn yardımcı kütüphaneleri. Üretimde rpID değeriniz, gerçek alan adınız (ör. example.com) olmalı; doğrulama başarısızlıklarının büyük kısmı rpID/domain uyumsuzluğundan kaynaklanır.

Adım 1: Kurulum ve bağımlılıklar

Örnek projeyi başlatmak için npx create-next-app@latest passkey-demo komutunu kullanın. Ardından sunucu ve istemci tarafı için popüler bir yardımcı set olan @simplewebauthn/server ve @simplewebauthn/browser paketlerini ekleyin: npm i @simplewebauthn/server @simplewebauthn/browser. Ortam değişkenleri için RP_NAME ve RP_ID tanımlayın (ör. RP_NAME="Passkey Demo", RP_ID="localhost" veya üretimde example.com).

Adım 2: Kayıt (Registration) akışı

Kayıt akışı iki uç noktadan oluşur: seçenek üretimi ve doğrulama. Sunucuda önce generateRegistrationOptions ile kullanıcıya özel bir challenge ve seçenekler oluşturulur. Örnek kullanım: const opts = generateRegistrationOptions({ rpName, rpID, userID, userName, attestationType: 'none', authenticatorSelection: { residentKey: 'preferred', userVerification: 'preferred' } }). Bu opts istemciye döndürülür ve tarayıcıda startRegistration(opts) çağrısı yapılır. Tarayıcı, cihazın güvenli alanında anahtar çifti üretir ve sonucu (credential) sunucuya gönderir.

Doğrulama aşamasında sunucuda verifyRegistrationResponse ile imza ve köken (origin) kontrolü yapılır. Başarılıysa kullanıcının hesabına credentialID, publicKey, signCount gibi alanları kaydedin. Birden fazla cihaza passkey eklenmesini desteklemek için kullanıcı başına birden çok credential saklamak iyi bir pratiktir.

Adım 3: Giriş (Authentication) akışı

Giriş için benzer şekilde önce generateAuthenticationOptions çağrılır. Kullanıcıya ait credential’lar biliniyorsa allowCredentials listesi ile sınırlandırabilir veya cihazın keşfedilebilir kimlik bilgilerini (discoverable credentials) desteklemek için boş bırakabilirsiniz. İstemci tarafında startAuthentication(opts) çalıştırılır ve elde edilen yanıt sunucuya doğrulama için gönderilir.

Sunucuda verifyAuthenticationResponse ile imza, challenge, origin, rpID ve sayacın (signCount) ilerleyişi kontrol edilir. Başarılı doğrulamada kullanıcı oturumunu başlatın ve credential’ın signCount değerini güncelleyin. Geriye dönük saldırıları önlemek için aynı imzayı tekrar kabul etmeyin.

İyi uygulamalar (Security + UX)

- HTTPS zorunludur: Üretimde daima HTTPS kullanın; rpID alan adınız ile origin (ör. https://example.com) örtüşmelidir. Geliştirmede localhost istisna olarak desteklenir.
- Biyometrik doğrulama: userVerification: 'required' seçeneği güvenliği artırır ancak bazı eski cihazlarda uyumluluğu azaltabilir. Dengeli yaklaşım için 'preferred' iyi bir başlangıçtır.
- Platform ve geçiş anahtarları: Kullanıcılara hem cihaz içi (platform) hem de harici güvenlik anahtarlarıyla kayıt seçeneği sunun.
- Hesap kurtarma: Passkey harika bir deneyim sunar; yine de e‑posta tabanlı oturum açma bağlantısı veya sınırlı süreli OTP gibi bir kurtarma kanalı tutun.
- Çoklu cihaz: iCloud Anahtar Zinciri veya Google Password Manager senkronizasyonu sayesinde kullanıcı farklı cihazlardan giriş yapabilir; bu durumda kullanıcı akışını basit ve yönlendirici metinlerle destekleyin.

Test, hata ayıklama ve dağıtım

Geliştirme sırasında WebAuthn’ı about://webauthn veya Chrome’un Geliştirici Araçları altındaki Sanal Kimlik Doğrulayıcı ile test edebilirsiniz. Gerçek cihaz testi için ngrok gibi tünelleme araçlarıyla geçici bir HTTPS alan adı edinip RP_ID’yi bu alan adına ayarlayın. iOS 16+, Android 9+ ve modern masaüstü tarayıcılar passkey’i destekler. Üretime alırken CORS, SameSite ve Secure bayraklı çerez ayarlarını kontrol edin; kimlik doğrulama uç noktalarınızı rate limit ve CSRF koruması ile güçlendirin.

Sık karşılaşılan hatalar ve çözümleri

- Invalid Relying Party ID: rpID ile sitenin alan adı eşleşmiyordur. Alt alan adlarında rpID üst etki alanı olabilir (ör. app.example.com için example.com).
- NotAllowedError: Kullanıcı tarayıcı diyalogunu iptal etmiştir veya zaman aşımı yaşanmıştır. İstemci tarafında daha anlaşılır hata mesajları ve tekrar dene düğmesi gösterin.
- User verification required: Sunucuda userVerification 'required' iken cihaz biyometrik doğrulama sunmuyorsa 'preferred' ile test edin.
- Counter mismatch: signCount geriye düştüyse credential’ı güvenlik gerekçesiyle askıya alın ve kullanıcıdan yeniden kayıt isteyin.

Sonuç

Passkey, güvenliği artırırken kullanıcı deneyimini hızlandıran güçlü bir yaklaşım. Next.js ile WebAuthn/FIDO2 entegrasyonu birkaç uç nokta ve doğru yapılandırmayla kısa sürede hayata geçebilir. Bu rehberdeki adımlarla kayıt ve giriş akışlarını kurabilir, üretimde HTTPS, rpID, sayım ve köken kontrolleriyle sisteminizi sertleştirebilirsiniz. Parolasız geleceğe geçiş için en iyi zaman, kullanıcılarınız hazır ve modern tarayıcılar destekliyorken bugündür.

22 Ekim 2025 Çarşamba

WebAuthn ve Passkey ile Parolasız Kimlik Doğrulama: Next.js + Node.js ile Uçtan Uca Kurulum

Giriş

Parolalar bitmek bilmeyen bir güvenlik ve kullanıcı deneyimi sorunu. WebAuthn ve Passkey (FIDO2) standartları, hem güvenliği artıran hem de kullanıcıyı zahmetten kurtaran parolasız kimlik doğrulama sunuyor. Bu yazıda, Next.js ve Node.js kullanarak uçtan uca bir WebAuthn akışını nasıl kuracağınızı adım adım anlatıyorum. Hem modern tarayıcı desteğini, hem de üretim ortamında dikkat edilmesi gerekenleri ele alacağız.

WebAuthn ve Passkey Nedir?

WebAuthn, W3C ve FIDO Alliance tarafından geliştirilen, tarayıcı üzerinden güvenli anahtar tabanlı kimlik doğrulama standardıdır. Passkey ise kullanıcıların cihazlarında saklanan ve bulut üzerinden senkronize olabilen (Apple iCloud, Google Password Manager vb.) WebAuthn kimlik bilgileridir. Kısaca: kullanıcı, parolaya gerek duymadan cihaz biyometrisi (Face ID, Touch ID, Windows Hello) veya güvenlik anahtarı (YubiKey) ile giriş yapar.

Kavramsal olarak iki akış var: Kayıt (Registration) ve Giriş (Authentication). Sunucu, benzersiz bir challenge üretir; tarayıcıda navigator.credentials.create() veya navigator.credentials.get() çağrıları yapılır; elde edilen yanıt sunucu tarafından doğrulanır. Doğrulama sonrası, kullanıcı artık parolasız giriş yapabilir.

Mimari Özeti

- Relying Party (RP): Uygulamanızın alan adıyla tanımlanır (ör. rpId: "ornek.com"). Bu değer kök alan adınız olmalıdır.

- Attestation ve Assertion: Kayıtta attestation, girişte assertion doğrulanır. Üretimde çoğunlukla attestation: "none" kullanılır.

- Depolama: Kamu anahtarı, credential ID ve counter gibi veriler sunucuda saklanır. Challenge için kısa süreli bir önbellek (Redis) önerilir.

Ön Koşullar

- Next.js 14+ (App Router önerilir), Node.js 18+.

- HTTPS zorunlu (geliştirmede localhost hariç). Üretimde gerçek bir alan adıyla test edin.

- Kütüphaneler: @simplewebauthn/server ve @simplewebauthn/browser. Bu ikili, challenge üretimi ve doğrulama işini hataya yer bırakmadan kolaylaştırır.

Adım 1: Projeyi Hazırlayın

Next.js projesini oluşturun ve bağımlılıkları kurun: npm i @simplewebauthn/server @simplewebauthn/browser. App Router ile app/api altında dört endpoint planlayın: /webauthn/register/options, /webauthn/register/verify, /webauthn/login/options, /webauthn/login/verify.

Sunucu tarafında yapılandırma için değişkenleri belirleyin: rpName, rpID (alan adınız), origin (ör. https://app.ornek.com). Bu üçü birbirine tam uyumlu olmalıdır; aksi halde tarayıcı doğrulamayı reddeder.

Adım 2: Kayıt (Registration) Akışı

1) Options üretimi: Sunucu, oturumu açık kullanıcının (ör. user.id, user.name) bilgileriyle generateRegistrationOptions çağırır. attestation: "none", authenticatorSelection için residentKey: "preferred" ve userVerification: "preferred" yeterlidir.

2) Challenge saklama: Dönen options.challenge değerini kullanıcının oturumuna veya Redis’e yazın. Bu değer tek kullanımlık ve kısa ömürlü olmalıdır.

3) İstemci işlem: Tarayıcıda startRegistration(options) veya yerel API ile navigator.credentials.create({ publicKey: options }) çağırın. Kullanıcı, cihaz biyometrisiyle onaylar ve bir attestation yanıtı oluşur.

4) Doğrulama: Yanıt sunucuya gönderilir ve verifyRegistrationResponse ile doğrulanır. Başarılıysa credentialID, publicKey, counter, transports gibi alanları veritabanına kaydedin.

Not: Binary verilerin JSON’a taşınmasında base64url dönüşümleri gerekir. @simplewebauthn bu dönüşümleri kolaylaştırır; farklı bir yaklaşım kullanıyorsanız, ArrayBuffer ↔ base64url dönüşümleri için tutarlı yardımcı fonksiyonlar geliştirin.

Adım 3: Giriş (Authentication) Akışı

1) Options üretimi: Sunucu generateAuthenticationOptions ile yeni bir challenge üretir. Dilerseniz sadece kullanıcıya ait allowCredentials listesi dönebilir veya passkey’lerin “discovered” kullanımına izin vermek için boş da bırakabilirsiniz.

2) İstemci işlem: Tarayıcıda startAuthentication(options) ya da navigator.credentials.get({ publicKey: options }) çağrılır. Kullanıcı biyometrik onayı verir.

3) Doğrulama: Sunucu, verifyAuthenticationResponse ile yanıtı doğrular; counter değerini günceller ve başarılıysa oturum veya token üretir (HTTP only, SameSite=Strict bir çerez önerilir).

Güvenlik ve Üretim İpuçları

- Origin ve rpID eşleşmesi: origin tam URL, rpID kök alan adı olmalı. https://login.ornek.com ile rpID: "ornek.com" uyumludur.

- HTTPS zorunlu: Geliştirme dışında güvenli olmayan kökenlerde WebAuthn çalışmaz.

- Attestation politikası: Kurumsal cihaz kökenini doğrulamak gerekmiyorsa none en pratik seçenek.

- Kullanıcı doğrulaması: userVerification: "required" güvenliği artırır; deneyim açısından “preferred” daha esnek olabilir.

- Passkey senkronizasyonu: Çok cihazlı deneyim için kullanıcıya aynı ekosistemde (iCloud / Google) senkronizasyonu etkinleştirmesini anlatın.

- Conditional UI: Chrome’da parolasız “otomatik” akış için navigator.credentials.get({ mediation: "conditional" }) ve ilgili bayrakları düşünün.

- Geri dönüş: İlk aşamada SMS/e-posta yedek yöntem bulundurun ancak uzun vadede phishing’e dayanıklı seçeneklere yönelin.

Sık Karşılaşılan Hatalar

- NotAllowedError: Kullanıcı akışı iptal etti veya tarayıcı UI zaman aşımına uğradı. Zaman aşımını düşürün ve açık geri bildirim gösterin.

- InvalidStateError: Aynı cihazda aynı kullanıcı için tekrar kayıt yapılmak isteniyor olabilir. Kayıt öncesi kullanıcıya mevcut passkey’leri gösterip yönetin.

- RP ID uyuşmazlığı: Alt alan adı/Origin ve rpID yanlış ayarlandığında doğrulama başarısız olur. Üretim alan adınızla birebir test edin.

Dağıtım ve Sonuç

Uygulamayı dağıtırken, ters proxy (Nginx) üzerinden HTTP → HTTPS zorlaması yapın. Load balancer arkasında gerçek istemci IP’sini günlüğe almak için X-Forwarded-For başlığını doğru iletin. CDN veya WAF kullanıyorsanız WebAuthn isteklerinin gövde boyutu ve header’larını kısıtlamadığından emin olun.

Sonuç olarak, WebAuthn ve Passkey ile Next.js + Node.js üzerinde parolasız kimlik doğrulama kurmak düşündüğünüzden daha erişilebilir. Doğru rpID/origin eşleşmesi, sağlam challenge saklama, güvenli çerez ayarları ve iyi bir kullanıcı akışı ile hem güvenlik seviyenizi yükseltir hem de dönüşüm oranlarını artırırsınız. Bugün basit bir kayıt/giriş prototipi hazırlayıp ekibinizle birlikte deneyin; parolaları geride bırakma vakti geldi.

3.