14 Aralık 2025 Pazar

Next.js ile Passkey (WebAuthn) Entegrasyonu: Şifresiz Giriş İçin Adım Adım Rehber

Giriş

Şifresiz kimlik doğrulama, web uygulamalarında güvenliği yükseltirken kullanıcı deneyimini de ciddi biçimde iyileştiriyor. Passkey (FIDO2/WebAuthn) tabanlı giriş, parolaları ortadan kaldırarak kimlik doğrulamayı cihazın güvenli donanımına emanet eder. Bu yazıda, Next.js ile Passkey entegrasyonunu adım adım ele alacak; sunucu ve istemci akışlarını, doğru yapılandırmayı, veri modelini ve canlıya alma ipuçlarını paylaşacağım.

Passkey ve WebAuthn Nedir?

WebAuthn, tarayıcı ile sunucu arasında kriptografik anahtarlar kullanarak kullanıcı doğrulamayı standartlaştırır. Passkey ise bu standardın son kullanıcıya yansıyan yüzü: Apple, Google ve Microsoft ekosistemlerinde anahtarlar güvenli biçimde saklanır ve cihazlar arasında senkronize olabilir. Kullanıcı, biyometri veya cihaz kilidi ile yetkilendirme yapar; sunucu tarafında hiçbir parola tutulmaz.

Neden Passkey?

- Kimlik avı (phishing) direncine sahiptir: Anahtarlar alan adına (RP ID) bağlıdır, başka bir sitede kullanılamaz.
- Kullanıcı deneyimi yüksektir: Parola üretme, hatırlama ve reset akışları büyük ölçüde ortadan kalkar.
- Uygulama bakım maliyeti azalır: Parola karma algoritmaları, karmaşık parola politikaları gibi işler minimize olur.

Önkoşullar ve Mimari

- Next.js 13/14 (App Router) veya 12 (Pages) ile Node.js 18+.
- Üretimde HTTPS zorunludur; geliştirmede localhost desteklenir.
- RP ID, alan adınız (ör. example.com) olmalı; origin tam URL’nizdir (ör. https://example.com).
- Sunucuda kriptografik doğrulama için Node runtime kullanın; Edge runtime, bazı kütüphanelerde sınırlı kalabilir.

Kütüphaneler ve Temel Akış

Node.js ekosisteminde @simplewebauthn/server ve tarayıcı tarafında @simplewebauthn/browser ile stabil bir deneyim elde edebilirsiniz. Kayıt (registration) ve giriş (authentication) iki ayrı fakat benzer akışla ilerler: Sunucu bir challenge üretir, tarayıcı navigator.credentials üzerinden güvenli cihaz akışını tetikler ve yanıt sunucuda doğrulanır.

Kayıt (Registration) Akışı

1) Sunucu uç noktası: /api/passkey/register/options
Sunucu generateRegistrationOptions ile kullanıcıya özgü bir challenge üretir. Parametrelerde rpID (alan adınız), rpName, user.id (kalıcı ve benzersiz), user.name, attestation (çoğunlukla none) ve discoverable credentials için authenticatorSelection.residentKey="preferred", userVerification="preferred" kullanabilirsiniz. Challenge’ı ve kullanıcı kimliğini kısa süreli (örn. 5 dk) Redis gibi bir depoda saklayın.

2) İstemci adımı:
Tarafınıza dönen PublicKeyCredentialCreationOptions ile @simplewebauthn/browser kütüphanesindeki startRegistration çağrılır. Tarayıcı biyometri/donanım akışını yönetir ve yanıt üretir.

3) Sunucu doğrulaması: /api/passkey/register/verify
verifyRegistrationResponse ile gelen veriyi doğrulayın. Başarılıysa veritabanına credentialId (Base64URL), publicKey, counter, transports, backedUp gibi alanları ekleyin. Aynı kullanıcı için birden fazla cihaz desteği sağlamak üzere bir “kullanıcı-kimlik bilgisi” tablosu kullanın.

Giriş (Authentication) Akışı

1) Sunucu uç noktası: /api/passkey/login/options
generateAuthenticationOptions ile challenge üretin. Kullanıcının e-posta veya kullanıcı adı verdiği senaryoda allowCredentials ile ilgili kimlik bilgilerini sınırlayabilir; tamamen kullanıcı adı girmeden “sinyalsiz” giriş için discoverable credentials’ı destekleyebilirsiniz.

2) İstemci adımı:
startAuthentication çağrısı tarayıcıda WebAuthn akışını tetikler; kullanıcı cihaz kilidi veya biyometri ile onaylar.

3) Sunucu doğrulaması:
verifyAuthenticationResponse ile yanıtı doğrulayın. Counter değeri artmıyorsa veya geriye gidiyorsa potansiyel klonlama şüphesi doğar; kontrol edip güncelleyin. Başarılı doğrulamada oturum belirtecini (HttpOnly, Secure, SameSite=Lax) ayarlayın.

Veri Modeli ve Saklama

Veri tabanı şeması örneği: user_credentials(id, user_id, credential_id, public_key, counter, transports, backed_up, created_at). credential_id ve public_key için Base64URL normalize edin. Kullanıcı silme ve cihaz yönetimi (ör. “Bu cihazı kaldır”) arayüzü sağlayın.

Yapılandırma Ayrıntıları ve İpuçları

- Origin/RP ID eşleşmesi kritik: https://app.example.com için RP ID example.com veya alt alan adınızın köküne uygun olmalı. 127.0.0.1 yerine localhost kullanın.
- HTTPS zorunlu; yalnızca http://localhost istisnadır.
- Attestation çoğu senaryoda “none”; kurumsal güven zinciri gereksiniminde metadata doğrulamayı (MDS) değerlendirin.
- userVerification: “required”, uygulamanızın risk profiline göre zorunlu biyometri sağlar.
- Challenge tek kullanımlık ve kısa ömürlü olmalı, tekrar kullanımda reddedilmeli.
- Edge vs Node: Doğrulama kütüphanesinin Node kriptosuna ihtiyacı olabilir; Next.js API Routes’ı Node runtime’da çalıştırın.

UX Önerileri

- Yeni kullanıcı kayıt akışında parolasız varsayılanı sunun; uygun cihaz yoksa e-posta sihirli bağlantı veya tek seferlik kod ile yedek akış bırakın.
- Giriş sayfasında “Passkey ile devam et” butonu tek tıklama ile süreci başlatmalı; başarısızlıkta otomatik olarak yedek akışa yönlendirin.
- Cihaz yönetimi sayfasında kayıtlı cihaz adlarını, eklenme tarihini ve kaldırma seçeneklerini gösterin.

Hata Ayıklama ve Sık Karşılaşılan Sorunlar

- “The relying party ID is not a registrable domain suffix” uyarısı: RP ID yanlış. Geliştirmede localhost kullanın; üretimde çıplak alan adı veya uygun alt alan.
- “NotAllowedError” hatası: Kullanıcı onaylamadı veya tarayıcı akışı zaman aşımına uğradı. Zaman aşımı süresini makul tutun ve net geri bildirim verin.
- “This device doesn’t support passkeys”: Eski OS/tarayıcı olabilir; güncellemeyi önerin ve yedek kimlik doğrulamasını aktif tutun.

Güvenlik En İyi Uygulamaları

- Oturum çerezlerini HttpOnly ve Secure olarak ayarlayın; CSRF riskine karşı SameSite=Lax veya CSRF belirteci kullanın.
- Rate limiting ve IP/cihaz parmak iziyle kötüye kullanımı azaltın.
- Kök alan adından başka ortamlara (staging) dağıtırken RP ID ve origin’i doğru güncelleyin.
- Yedek kurtarma (ör. e-posta + ek doğrulama) ve cihaz kaybı senaryolarını önceden tasarlayın.

Sonuç

Passkey (WebAuthn), modern web uygulamalarında güvenlik ve kullanılabilirliği aynı anda yükselten bir yapı taşı. Next.js ekosisteminde @simplewebauthn ile kısa sürede kayıt ve giriş akışlarını hayata geçirebilir, phishing’e dirençli, hızlı ve kullanıcı dostu bir kimlik doğrulama deneyimi sunabilirsiniz. Doğru RP ID/origin eşleşmesi, kısa ömürlü challenge’lar ve sağlam bir cihaz yönetimi arayüzü ile üretime hazır bir çözüm elde etmek zor değil.

Hiç yorum yok: