şifresiz giriş etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
şifresiz giriş etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

30 Kasım 2025 Pazar

Passkey (WebAuthn) ile Şifresiz Giriş: Next.js ve SimpleWebAuthn ile Uçtan Uca Kurulum

Passkey (WebAuthn) ile Şifresiz Giriş: Adım Adım Uygulama Rehberi

Parola yorgunluğu, kimlik avı ve SMS tabanlı doğrulamanın zayıflıkları derken, modern web uygulamalarında şifresiz giriş kaçınılmaz hale geldi. Passkey’ler, WebAuthn ve FIDO2 standartlarıyla desteklenen, biyometri veya cihaz kilidiyle korunan anahtar çiftlerine dayanır. Kullanıcı deneyimini hızlandırır, kimlik avına dayanıklıdır ve iCloud Anahtar Zinciri ile Google Password Manager gibi yöneticiler arasında senkronize olabilir. Bu yazıda, Next.js ve SimpleWebAuthn kütüphanesi ile uçtan uca bir passkey (WebAuthn) entegrasyonunu nasıl kuracağınızı adım adım anlatıyorum.

Neden Passkey?

Passkey, kullanıcının cihazında saklanan bir özel anahtar ile sunucunun sakladığı açık anahtarın eşleşmesine dayanır. Parola gönderilmez, dolayısıyla veri tabanı sızıntılarında parolaların çalınması gibi riskler ortadan kalkar. Kullanıcı cihazında biyometri (Face ID, Touch ID), donanım anahtarı (YubiKey) veya cihaz PIN’i ile doğrulama yapar. Tarayıcı ve platform desteği artık yaygınlaştı; Chrome, Safari ve Firefox, iOS/Android ve masaüstü işletim sistemlerinde kullanılabiliyor.

Mimari ve Gereksinimler

WebAuthn iki ana akış içerir: kayıt (registration) ve kimlik doğrulama (authentication). Her akışta sunucu benzersiz bir challenge üretir, istemci tarafında tarayıcı navigator.credentials API’si ile doğrulama cihazıyla imza atılır ve bu yanıt sunucuda doğrulanır. Üretimde HTTPS zorunludur ve RP ID (Relying Party ID) alan adınızla birebir eşleşmelidir (ör. rpID = example.com).

Teknoloji Seçimi

Örnek kurulum için Next.js 14 (Route Handlers veya App Router), sunucu tarafında @simplewebauthn/server, istemci tarafında @simplewebauthn/browser kullanılabilir. Veritabanı olarak Postgres veya bir KV deposu tercih edebilirsiniz. Saklanacak başlıca alanlar: kullanıcı kimliği, credentialID, publicKey, counter ve tercihen cihaz/metaveri.

Kayıt Akışı (Registration)

1) Kullanıcı e-posta/ID ile kayıt başlatır. Sunucu generateRegistrationOptions ile seçenekleri üretir, challenge’ı geçici olarak saklar ve istemciye döner. Örnek:

const opts = generateRegistrationOptions({ rpName: 'Uygulama Adı', rpID: 'example.com', userName: 'ali', userID: 'user-123', attestationType: 'none', authenticatorSelection: { residentKey: 'preferred', userVerification: 'preferred', authenticatorAttachment: 'platform' } });

2) İstemci, tarayıcıda @simplewebauthn/browser yardımıyla kullanıcıdan biyometri izni ister ve kimlik bilgisi oluşturur:

const attResp = await startRegistration(opts);

3) Sunucu, verifyRegistrationResponse ile gelen cevabı doğrular; doğrulama başarılıysa credentialID, publicKey ve counter değerlerini kullanıcıyla ilişkilendirerek kalıcı olarak saklar.

Giriş Akışı (Authentication)

1) Kullanıcı giriş sayfasında e-posta/ID girer veya koşullu UI ile otomatik olarak öneri alır. Sunucu generateAuthenticationOptions ile yeni bir challenge üretir. İsteğe bağlı olarak yalnızca ilgili kullanıcının kayıtlı cihazlarını allowCredentials ile sınırlandırabilirsiniz.

2) İstemci tarafında çağrı yapılır:

const authResp = await startAuthentication(options);

3) Sunucu verifyAuthenticationResponse ile imzayı ve origin/rpID alanlarını doğrular, counter değerini günceller. Başarılıysa oturumu (cookie/JWT) kurar.

Koşullu UI (Conditional Mediation) ile Tek Tık Giriş

Chrome ve destekleyen tarayıcılarda, kullanıcı adı alanı odaktayken passkey önerilerini otomatik gösterebilirsiniz. Basitçe bir email input’unuz varken:

navigator.credentials.get({ publicKey: authOptions, mediation: 'conditional' });

Bunun çalışması için sayfanız HTTPS olmalı, autocomplete öznitelikleri doğru ayarlanmalı ve kullanıcı daha önce passkey kaydetmiş olmalıdır. Bu yöntem giriş sürtünmesini ciddi şekilde azaltır.

Güvenlik İpuçları ve En İyi Uygulamalar

- RP ID alan adınızla aynı olmalı; yerelde test ederken localhost kullanın veya geçerli bir sertifika ile alt alan adı hazırlayın.

- attestationType: 'none' çoğu senaryo için en iyisidir; gereksiz attestation verisi toplamayın.

- userVerification için 'required' yüksek güvenlikli sayfalar için uygundur (örn. ödeme, ayarlar). Genel girişte 'preferred' iyi bir dengedir.

- Kullanıcıların cihaz değiştirme/ekleme senaryoları için birden fazla passkey kaydına izin verin ve kurtarma seçenekleri (e-posta bağlantısı veya destek akışı) sunun.

- Rate limit, yeniden oynatma (replay) engelleme, kaynak (origin) ve challenge ömrünü doğrulamayı ihmal etmeyin.

Hata Ayıklama ve Test

- SecurityError: The operation is insecure genelde HTTPS veya RP ID uyuşmazlığını gösterir.

- NotAllowedError kullanıcı etkileşimi yokken veya işlemi iptal ettiğinde görülür; buton tıklamasıyla tetikleyin.

- Unknown authenticator veya eşleşmeyen credentialID için doğru kullanıcıyla ilişkilendirme yapıldığından emin olun.

- Tarayıcı konsolu ve about://webauthn (Chrome) test araçları ile sanal güvenlik anahtarı oluşturup akışları yerelde deneyebilirsiniz.

Performans ve UX

Passkey akışı minimal JSON veri alışverişine dayanır; SSR ve edge işleme ile gecikmeyi azaltabilirsiniz. Başarılı kayıt sonrası kullanıcının cihazı üzerinde parolayı da “kaldırmayı” önermek, geçişi hızlandırır. Kullanıcıya hangi cihazların kayıtlı olduğunu gösteren bir yönetim ekranı sunmak güveni artırır.

Sonuç

Passkey (WebAuthn) ile şifresiz giriş, güvenliği artırırken kullanıcı deneyimini de basitleştirir. Next.js ve SimpleWebAuthn ile kurulumu birkaç uç noktaya indirgenebilir: kayıt için seçenek üretme/doğrulama ve giriş için seçenek üretme/doğrulama. RP ID, HTTPS ve challenge yönetimi gibi kritik ayrıntılara dikkat ettiğiniz sürece, modern tarayıcılarda hızlı ve güvenli bir oturum altyapısı sağlayabilirsiniz.

20 Kasım 2025 Perşembe

Passkey (WebAuthn) ile Şifresiz Giriş Uygulaması: Adım Adım Geliştirici Rehberi

Giriş

Şifresiz kimlik doğrulama, hem güvenliği artırmak hem de kullanıcı deneyimini iyileştirmek için son yılların en önemli trendlerinden biri. Passkey (WebAuthn/FIDO2) yaklaşımı, parola sızıntılarını ve kimlik avı risklerini azaltırken tek dokunuşla giriş deneyimi sunuyor. Bu yazıda, modern bir web uygulamasına passkey tabanlı şifresiz girişi nasıl entegre edebileceğinizi adım adım ele alacağız. Anlatım sade, SEO uyumlu ve güncel standartları takip edecek şekilde hazırlandı.

Passkey Nedir ve Neden Önemlidir?

Passkey, FIDO2 ve WebAuthn standartlarının bir ürünüdür. Kullanıcının cihazında güvenli bir şekilde saklanan asimetrik anahtar çifti ile çalışır. Sunucu sadece kullanıcının açık anahtarını tutar; özel anahtar cihazdan çıkmaz. Böylece parola sızıntıları, tekrar kullanım ve kimlik avı (phishing) riskleri büyük ölçüde azalır. Ek olarak, platform doğrulayıcıları (iOS/Android/Windows/macOS) ve bulut senkronizasyonu sayesinde kullanıcı deneyimi neredeyse otomatik doldurma kadar kolay hale gelir.

Temel Kavramlar

Relying Party (RP) ID, genellikle uygulamanızın kök etki alanıdır ve WebAuthn işlemlerinin bağlandığı kimliktir. Origin ise protokol, alan adı ve portun birleşimidir; HTTPS zorunludur. Kayıt sırasında attestation, giriş sırasında assertion adı verilen imzalı veriler üretilir. Sunucu bu verileri doğrular, sayaç (signCount) ile tekrar saldırılarını engeller ve açık anahtarı (public key) güvenli şekilde saklar.

Gereksinimler

Üretimde HTTPS zorunludur; geliştirirken localhost istisna olarak desteklenir. Sunucu tarafında bir WebAuthn doğrulama kütüphanesi kullanmanız pratik olacaktır. Veritabanında kullanıcı kimliği ile eşleştirilmiş credentialId, publicKey, signCount, transports ve tercihe göre attestation bilgilerini saklamalısınız. Tarayıcı tarafında WebAuthn API’sini (navigator.credentials) kullanacaksınız.

Adım 1: RP ID ve Origin Doğrulaması

RP ID, example.com gibi kaydedilebilir kök alan adı olmalıdır. Alt alan adlarında çalışan uygulamalar için RP ID’yi kök alan olarak belirlemek, farklı alt alanlarda aynı passkey’i kullanabilmenizi sağlar. Üretimde https://example.com gibi tam bir origin kullanmalı ve yönlendirmelerinizin origin’i değiştirmediğinden emin olmalısınız.

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

Önce sunucu, benzersiz bir challenge üretir ve istemciye publicKeyCredentialCreationOptions ile gönderir. Bu seçeneklerde rp, user, challenge, pubKeyAlg (örn. ES256), authenticatorSelection (residentKey ve userVerification tercihleri) ve timeout gibi değerler bulunur. İstemci, navigator.credentials.create({ publicKey: options }) çağrısı ile passkey oluşturur. Elde edilen attestation yanıtını sunucuya gönderirsiniz. Sunucu tarafında imza doğrulanır, RP ID hash’i ve origin kontrol edilir, ardından credentialId, publicKey ve signCount veritabanına kaydedilir. Kullanıcı deneyimi için kayıt sırasında en az iki farklı cihazda passkey oluşturmayı önermek, hesabın kurtarılabilirliğini artırır.

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

Girişte sunucu yeni bir challenge üretir ve publicKeyCredentialRequestOptions ile istemciye gönderir. Eğer keşfedilebilir kimlik bilgileri (discoverable credentials) kullanıyorsanız kullanıcı adı sormadan doğrudan passkey seçimi mümkün olur. İstemci navigator.credentials.get({ publicKey: options }) çağrısı ile assertion üretir. Sunucu imzayı ve sayaç artışını doğrular; signCount beklenenden düşükse anahtarın çoğaltılmış olabileceğine dair alarm üretir. Başarılı doğrulamadan sonra oturum açılır ve standart oturum yönetimi (cookie veya token) uygulanır.

Adım 4: Conditional UI ve Otomatik Doldurma

Uygun tarayıcılarda “conditional UI” ile kullanıcı adı alanında beklerken passkey önerileri gösterilebilir. Bu deneyim için mediation: "conditional" parametresi ve ilgili tarayıcı desteği gerekir. Kullanıcı adı girmeden tek dokunuşla giriş, dönüşüm oranlarını belirgin biçimde artırabilir.

Güvenlik En İyi Uygulamaları

HTTPS her zaman zorunlu olmalıdır. userVerification’ı mümkünse required yaparak biyometrik/PIN doğrulaması isteyin. COSE algoritmalarını ES256 gibi modern seçeneklerle sınırlayın. Timeout değerlerini gerçekçi tutun ve hataları ayrıntılı ama saldırgana ipucu vermeyecek şekilde loglayın. RP ID ve origin uyuşmazlıkları, SecurityError hatalarının en yaygın sebebidir; alan adı, www/alt alan ayrımları ve proxy ayarlarını dikkatle kontrol edin.

Veri Tabanı Tasarımı

Kullanıcı başına birden çok credential saklayın. Her kayıt için credentialId (ikili/BASE64URL), publicKey (COSE/PEM), signCount (tamsayı), transports (usb, nfc, ble, internal), aaguid ve oluşturulma tarihi alanları tutarlı bir şema oluşturur. Silinen veya kaybolan cihazlar için güvenli kaldırma (soft delete) ve denetim kayıtları (audit log) eklemeniz önerilir.

UX İpuçları

Kullanıcıyı bilgilendiren net mikro metinler kullanın: “Cihaz kilidini açın ve dokunun” gibi. Başarısız denemelerde net ama güvenli hata mesajları verin. İlk kayıt sonrasında “Başka bir cihaz ekle” önerisi sunarak kurtarma olasılığını artırın. Passkey’i mevcut parolalı hesaplara ek ikinci faktör olarak başlatıp zamanla parolayı kaldırma stratejisi de uygulanabilir.

Hata Ayıklama ve Yaygın Sorunlar

NotAllowedError genellikle kullanıcı işlemi iptal ettiğinde veya zaman aşımında görülür. SecurityError RP ID/origin uyumsuzluğunu işaret eder. UnknownError donanım doğrulayıcı veya platform politikası sorunlarına işaret edebilir. Windows Hello için cihazda PIN/Biyometri etkin olmalı; mobilde ekran kilidi şarttır.

Sonuç

Passkey (WebAuthn) ile şifresiz giriş, modern web projelerinde güvenliği artırırken sürtünmeyi azaltır. Doğru RP ID, güvenli sunucu doğrulaması, kullanıcı dostu akış ve çok cihazlı strateji ile hem ölçeklenebilir hem de dayanıklı bir kimlik doğrulama katmanı kurabilirsiniz. Bugünden küçük bir pilotla başlayıp kullanıcı geri bildirimlerine göre geliştirmek, geçiş maliyetini düşürmenin en verimli yoludur.

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.

10 Ekim 2025 Cuma

Passkeys ile Şifresiz Giriş: WebAuthn + FIDO2 ile Adım Adım Uygulama Rehberi

Passkey nedir ve neden şimdi?

Parola sızıntıları, oltalama (phishing) ve zayıf parola alışkanlıkları yıllardır güvenlik ekosisteminin en zayıf halkası. Passkey, FIDO2 standartları ve WebAuthn API’si üzerine inşa edilen, kullanıcıların yalnızca cihazlarındaki biyometrik doğrulama (parmak izi, Face ID, Windows Hello) veya PIN ile oturum açmasını sağlayan şifresiz bir yöntemdir. Parolalar yok, tek kullanımlık SMS kodları yok; kriptografik anahtar çifti ve tarayıcı desteği var. Apple, Google ve Microsoft’un ekosistemlerinde senkronize edilebilen passkey’ler hem güvenliği hem de dönüşüm oranlarını artırır.

Bu rehberde, modern bir web uygulamasına passkey tabanlı kayıt ve giriş akışını nasıl ekleyeceğinizi, hangi teknik ayrıntılara dikkat etmeniz gerektiğini ve yaygın hataları nasıl önleyeceğinizi anlatıyorum. Anlatım sade, adımlar somut; odak noktamız uygulanabilirlik.

Mimariye hızlı bakış

WebAuthn, üç aktörle çalışır: Relying Party (siteniz), istemci (tarayıcı) ve authenticator (platform veya harici anahtar). Kayıt sırasında site, tarayıcıya bir challenge ve ayarlar gönderir; cihazda bir anahtar çifti oluşturulur, siteniz genel anahtarı güvenli şekilde kaydeder. Girişte, site bir challenge ile imza ister; cihaz, kullanıcı doğrulaması sonrası imzayı üretir ve siteniz bunu doğrular. Parola asla yok; kimlik doğrulama domain’e (rpId) bağlı olduğu için oltalama büyük ölçüde engellenir.

Önkoşullar ve kurulum gereksinimleri

- HTTPS zorunlu: WebAuthn yalnızca güvenli origin’lerde çalışır. Geliştirme için localhost istisnadır.

- rpId ve origin: rpId genellikle alan adınızdır (ör. example.com). Alt alanlardan çağırıyorsanız bunu planlayın.

- Session ve CSRF: Challenge değerlerini oturumda tutun; her istek için taze ve tekil challenge üretin. SameSite=Lax/Strict çerezleri tercih edin.

- Tarayıcı desteği: Chrome, Edge, Safari ve Firefox güncel sürümlerde passkey destekliyor. iOS 16+, Android 9+ geniş kapsama sahip.

Kayıt akışı: Sunucu tarafı

1) Kullanıcı kayıt butonuna bastığında sunucu benzersiz bir challenge üretir ve oturumda saklar. Ardından istemciye PublicKeyCredentialCreationOptions döndürür: { rp: { name, id }, user: { id, name, displayName }, challenge, pubKeyCredParams, authenticatorSelection, attestation }.

2) user.id değeri kararlı ve benzersiz olmalı (ör. 16-32 baytlık bir UUID veya key). Kullanıcı adını değiştirse bile user.id sabit kalmalıdır.

3) Attestation’ı çoğu senaryoda "none" olarak ayarlayın; gizlilik ve uyumluluk açısından yeterlidir.

4) İstemciden dönen attestationObject ve clientDataJSON alanlarını doğrulayın: challenge eşleşmesi, origin kontrolü ve attestation formatı. Başarılıysa credentialId, publicKey ve signCount’ı veritabanında kullanıcıyla eşleştirerek saklayın.

Giriş akışı: Sunucu ve istemci

1) Sunucu, giriş başlatıldığında yine tekil bir challenge üretir ve PublicKeyCredentialRequestOptions döndürür: { challenge, rpId, allowCredentials?, userVerification }. Passkey-first deneyimi için discoverable credentials (resident key) kullanımını tercih edebilirsiniz; bu durumda allowCredentials boş bırakılabilir.

2) İstemci tarafında, kayıt için navigator.credentials.create({ publicKey }), giriş için ise navigator.credentials.get({ publicKey }) çağrıları yapılır. Mobilde ve masaüstünde tarayıcı, sistem düzeyi biyometri istemini kendisi yönetir.

3) Dönen authenticatorData, clientDataJSON ve signature sunucuya gönderilir. Sunucu, ilgili publicKey ile imzayı doğrular, signCount artışını kontrol eder ve oturumu başlatır.

Conditional UI ve kullanıcı adı olmadan giriş

Chrome ve Android’de Conditional UI ile otomatik doldurma benzeri bir passkey deneyimi sunabilirsiniz. navigator.credentials.get({ publicKey, mediation: "conditional" }) şeklinde çağrıldığında kullanıcı adı alanına odaklanıldığında tarayıcı passkey önerir. Bu, “username-less” akışlarla birleştiğinde form sürtünmesini ciddi şekilde azaltır.

En iyi uygulamalar

- Resident key desteğini açın: authenticatorSelection: { residentKey: "preferred", userVerification: "required" }. Böylece kullanıcı adı olmadan giriş mümkün olur.

- Base64url dönüşümlerine dikkat: Tarayıcı ArrayBuffer döndürür; sunucuya gönderirken ve doğrularken URL-safe kodlama kullanın.

- Çoklu cihaz stratejisi: Passkey’ler iCloud Anahtar Zinciri ve Google Password Manager ile eşzamanlanabilir. Kullanıcıların ikinci cihaz eklemesini ve donanımsal anahtarları (YubiKey) desteklemeyi düşünün.

- Geri kazanım planı: Cihaz kaybında kilitlenme yaşanmaması için e-posta bağlantısı veya destek kanıtı gibi güvenli kurtarma akışları tasarlayın. Parolaya dönmek yerine sınırlı ayrıcalıklı, denetimli akışlar tercih edin.

Test ve hata ayıklama

- Chrome DevTools’ta Virtual Authenticator ile farklı authenticator türlerini ve UV/UP kombinasyonlarını simüle edin. chrome://webauthn üzerinden test kolaydır.

- Origin ve rpId uyuşmazlıkları en yaygın sorundur. Üretimde www ve kök alan adı tutarsızlıklarını önleyin.

- Sunucu saat senkronizasyonu, proxy ve CDN başlıkları (X-Forwarded-Proto) için yapılandırmalarınızı kontrol edin; HTTPS algısı bozulursa WebAuthn başarısız olabilir.

Güvenlik ve uyumluluk notları

Passkey’ler kimlik bilgilerinin etki alanına bağlanması sayesinde oltalamaya dirençlidir. Ortadaki adam saldırıları, parolalara göre anlamlı ölçüde zorlaşır. Kurumsal ortamlarda cihaz yönetimi, anahtar yedekleme politikaları ve regülasyon (KVKK/GDPR) gerekliliklerini değerlendirin. Attestation’a yalnızca gerçekten cihaz tedarik zinciri doğrulaması gerekiyorsa başvurun; aksi halde gizlilik dostu none yeterlidir.

Sonuç: Şifresiz geleceğe bugünden geçin

Passkey, kullanıcılar için sürtünmeyi azaltırken güvenliği yükselten nadir teknoloji kırılımlarından biri. Kayıt ve giriş akışlarında WebAuthn’u doğru kurguladığınızda, dönüşüm oranlarınız artar ve destek yükünüz azalır. Adımları küçükten büyüğe taşıyın: önce HTTPS ve rpId düzeni, sonra resident key ve conditional UI, en sonunda çoklu cihaz ve kurtarma planları. Bir kez doğru kurguladığınızda, şifresiz girişin kullanıcı memnuniyetine ve güvenliğe etkisini doğrudan göreceksiniz.

2 Ekim 2025 Perşembe

Passkey (FIDO2/WebAuthn) ile Şifresiz Giriş: Node.js Üzerinde Adım Adım Kurulum ve En İyi Uygulamalar

Passkey ve WebAuthn Nedir?

Passkey, FIDO2 ve WebAuthn standartları üzerine kurulu, şifre gerektirmeyen modern bir kimlik doğrulama yöntemidir. Kullanıcılar parolayı ezberlemek yerine, cihazlarının biyometrik sensörlerini (parmak izi, yüz tanıma) veya bir ekran kilidini kullanarak giriş yapar. Kriptografik anahtarlar cihazda güvenle saklanır ve çoğu ekosistemde (Apple, Google, Microsoft) bulut üzerinden yedeklenip eşitlenebilir. Bu sayede hem güvenlik artar hem de giriş deneyimi tek dokunuşa iner.

Neden Passkey Kullanmalısınız?

Şifreler kimlik avı, sızan veri setleri ve tekrar kullanım sorunları nedeniyle saldırı yüzeyini genişletir. Passkey ise tarayıcı ve cihaz düzeyinde kimlik bağlamı (origin + rp.id) zorunluluğu ile phishing’e kapıyı kapatır. Ayrıca hızlıdır, kullanıcı memnuniyetini artırır ve destekleyen tarayıcılarda ek yazılım gerektirmeden çalışır. Kısacası güvenlik, hız ve dönüşüm oranı açısından net bir kazanım sağlar.

Mimarinin Özeti

WebAuthn iki ana akıştan oluşur: kayıt (registration/attestation) ve giriş (authentication/assertion). Sunucu benzersiz bir challenge üretir, istemci bunu güvenli donanımda imzalar ve sunucu doğrular. Başarılı kayıt sonunda kullanıcıya ait credentialId, publicKey ve signCount gibi meta veriler veritabanında saklanır. Girişte de benzer şekilde sunucu yeni bir challenge üretir, istemcinin imzasını doğrular ve sayacı günceller.

Gereksinimler ve Hazırlık

- Etki alanınız HTTPS üzerinde çalışmalıdır. Geliştirme için https://localhost istisnai olarak geçerlidir.
- rp.id (relying party id) genellikle alan adınızın eTLD+1 karşılığıdır (ör. example.com). Alt alan adında çalışsanız bile rp.id çoğunlukla kök alan olmalıdır.
- Node.js tarafında popüler kütüphane olarak @simplewebauthn/server ve istemci için @simplewebauthn/browser tercih edebilirsiniz.

Adım Adım Kurulum (Node.js)

Adım 1 – Proje kurulumu: Sunucu için Express veya Fastify kullanabilirsiniz. Temel bağımlılıklar: @simplewebauthn/server, oturum yönetimi için bir middleware ve kalıcı saklama için bir veritabanı (ör. PostgreSQL).

Adım 2 – Kayıt seçeneklerini üretin: /register/generate-options uç noktasında PublicKeyCredentialCreationOptions üretin. rp.name ve rp.id, user.id, user.name, pubKeyCredParams ve authenticatorSelection alanlarını doldurun. authenticatorSelection.userVerification için “required” seçimi güvenliği artırır. Üretilen challenge’ı kullanıcı oturumuna yazın.

Adım 3 – Kayıt doğrulama: İstemci tarafından dönen navigator.credentials.create() sonucu ile /register/verify uç noktasında verifyRegistrationResponse çağrısını yapın. Başarılıysa credentialId, publicKey, counter ve transports bilgilerini veritabanında kullanıcıya bağlayın.

Adım 4 – Giriş seçeneklerini üretin: /login/generate-options uç noktasında PublicKeyCredentialRequestOptions döndürün. allowCredentials alanına kullanıcının kayıtlı credentialId’lerini ekleyin. Tek tık deneyimi için residentKey destekliyorsanız discovery senaryosunu da tasarlayın.

Adım 5 – Giriş doğrulama: İstemcinin navigator.credentials.get() yanıtını /login/verify uç noktasına gönderip verifyAuthenticationResponse ile kontrol edin. İmza geçerliyse oturumu başlatın ve signCount değerini güncelleyin.

İstemci (Tarayıcı) Akışı

Kayıt sırasında sunucudan aldığınız creationOptions ile navigator.credentials.create({ publicKey: creationOptions }) çağrısı yapın. Sonucu sunucuya POST edin. Girişte ise requestOptions ile navigator.credentials.get({ publicKey: requestOptions }) çağrısı yapın. Bu çağrılar kullanıcıyı biyometrik sensör veya cihaz kilidiyle onay vermeye yönlendirir.

Test, Hata Ayıklama ve Uyumluluk

Chrome DevTools’ta “WebAuthn” paneliyle sanal authenticator ekleyebilir, platform ve çapraz platform seçeneklerini simüle edebilirsiniz. Sık karşılaşılan hatalar: NotAllowedError (kullanıcı iptal etti veya zaman aşımı), DOMException: SecurityError (rp.id ve origin uyumsuz), Constraint hataları (ör. residentKey politikası). Üretimde hem platform (telefon, laptop) hem de harici güvenlik anahtarlarını test edin.

Güvenlik ve En İyi Uygulamalar

- Bütünleşik phishing direnci için rp.id ve site origin eşleşmesine dikkat edin.
- Challenge değerini kriptografik olarak güvenli rastgelelik ile üretin ve tek kullanımlık olarak saklayın.
- userVerification’ı “required” kullanmak; başkasının cihazı üzerinden kötüye kullanım riskini azaltır.
- Birden fazla cihaz senkronizasyonunu desteklemek için kullanıcıya birden çok credential eklemeye izin verin.
- Güvenlik anahtarı kaybı için kurtarma akışları (ikinci passkey, e-posta linki, müşteri desteği) tasarlayın.

UX Önerileri

Passkey’i bir opsiyon olarak sunmak yerine “Passkey ile giriş yap” butonunu ön plana alın. Uyumlu tarayıcı ve cihazlarda otomatik doldurma istemini tetiklemek için form alanlarınızı sade tutun. Kayıt sırasında cihaz adını kullanıcıdan alarak (ör. “Mert’in iPhone’u”) hesap ayarlarında listelemeyi kolaylaştırın. Passkey bulunmazsa parolasız alternatif olarak sihirli bağlantı (magic link) sunmak terk oranını düşürür.

Dağıtım ve Aşamalı Geçiş

Mevcut oturum açma sisteminizi bozmadan aşamalı geçiş yapabilirsiniz. Önce kayıtlı kullanıcılarınıza ek kimlik doğrulama metodu olarak passkey tanımlama imkanı verin. Kullanıcı davranışı oturursa parolayı isteğe bağlı hale getirin ve yeni kullanıcılara “passkey-öncelikli” deneyim sunun. CDN veya ters proxy katmanında HTTPS ve HSTS ayarlarının doğru olduğundan emin olun.

Sonuç

Passkey (FIDO2/WebAuthn), şifrelerin yarattığı güvenlik risklerini ve kullanıcı sürtünmesini önemli ölçüde azaltır. Node.js ekosistemindeki olgun kütüphaneler sayesinde entegrasyon birkaç uç noktayı uygulamak kadar basit hale geldi. Doğru rp.id yapılandırması, güvenli challenge yönetimi ve iyi bir UX ile dakikalar içinde modern, phishing dayanıklı ve tek dokunuşla giriş deneyimini hayata geçirebilirsiniz.

13 Eylül 2025 Cumartesi

Passkey (WebAuthn) ile Şifresiz Giriş Entegrasyonu: Adım Adım Rehber

Passkey nedir ve neden önemli?

Geleneksel parolalar hem kullanıcı deneyimi açısından sorunlu hem de güvenlik zaafları nedeniyle verimsizdir. Passkey, FIDO2 ve WebAuthn standartlarına dayalı, phishing’e dayanıklı ve cihaz tabanlı bir kimlik doğrulama yöntemidir. Kullanıcılar artık “123456” gibi zayıf parolalarla uğraşmak yerine, platformlarının (iOS, Android, Windows, macOS) yerleşik biyometrik doğrulamasını veya donanım anahtarını kullanır. Bu yazıda, modern bir web uygulamasına passkey ile şifresiz girişin nasıl ekleneceğini, mimari prensipleri ve dikkat edilmesi gereken güvenlik detaylarını anlatıyorum.

Temel mimari ve kavramlar

WebAuthn iki temel akıştan oluşur: Kayıt (Registration) ve Giriş (Authentication). Kayıt sırasında tarayıcı bir anahtar çifti üretir ve sunucuya sadece public key ve credentialId gibi meta veriler iletilir. Girişte, sunucu tarafından üretilen tek kullanımlık challenge imzalanarak doğrulama yapılır.

Önemli alanlar: rpId (Relying Party ID, genellikle alan adınız), origin (tam köken, ör. https://app.siteniz.com), userHandle (kullanıcının uygulama içi benzersiz kimliği), signCount (anti-rollback sayacı). Her doğrulamada challenge rastgele üretilir ve tek seferliktir.

Önkoşullar ve teknoloji seçimi

Üretimde HTTPS zorunludur. Geliştirme için localhost istisnası vardır. Sunucu tarafında doğrulama için hazır kütüphaneler tercih edin: Node.js için SimpleWebAuthn, Go için duo-labs/webauthn, Java için WebAuthn4J, Python için webauthn. İstemci tarafında tarayıcı API’si navigator.credentials üzerinden erişilir. Veritabanında her kullanıcı için birden fazla credential saklamaya hazır olun (cihaz kaybı senaryosu).

Kayıt (Registration) akışı

1. Sunucu hazırlığı: Kullanıcı hesabı oluşturulduğunda veya “Passkey ekle” tıklandığında sunucu bir PublicKeyCredentialCreationOptions üretir. İçerik: rp (name, id), user (id, name, displayName), challenge (kriptopratik rastgele dizi), pubKeyCredParams (genelde -7 ES256), authenticatorSelection (ör. residentKey: "preferred", userVerification: "required"), attestation ("none" çoğu senaryo için yeterli).

2. İstemci isteği: Tarayıcıda navigator.credentials.create({ publicKey: options }) çağrılır. Kullanıcı, biyometrik veya PIN ile onaylar. Tarayıcı size attestation yanıtını döner.

3. Sunucu doğrulaması: İstemciden dönen cevabı sunucuda kütüphane ile doğrulayın. Origin ve rpId eşleşmeli, challenge doğru olmalı. Başarılıysa şu verileri saklayın: credentialId (base64url), publicKey, signCount, transports (ör. "internal", "usb", "ble"), userId. attestation politikanıza göre sertifika zinciri doğrulamasını atlayabilir veya sıkı modda açabilirsiniz.

Giriş (Authentication) akışı

1. Sunucu challenge üretimi: Giriş sayfasında kullanıcı e-posta veya kullanıcı adını girince sunucu PublicKeyCredentialRequestOptions döner: challenge, rpId, allowCredentials (ilgili credentialId listesi) ve userVerification ("required" önerilir).

2. İstemci doğrulaması: navigator.credentials.get({ publicKey: options }) çağrılır. Tarayıcı kullanıcıdan biyometrik onay ister ve assertion döner.

3. Sunucu doğrulaması: İmza ve authenticatorData kontrol edilir; rpIdHash ve origin eşleşmeli. signCount daha büyükse güncellenir, geriye düşüyorsa potansiyel klon/hatalı cihaz işareti olarak reddedilir. Başarılıysa güvenli bir session veya token üretin.

Kullanıcı deneyimi: Conditional UI ve otomatik doldurma

Conditional UI (Chromium) ile kullanıcı adını sormadan doğrudan mediation: "conditional" parametresiyle passkey önerisini tarayıcıda tetikleyebilirsiniz. iOS ve Safari tarafında sistem otomatik doldurma panelindeki “Anahtarlar” akışı devreye girer. Parola yerine “Devam etmek için cihazınızı doğrulayın” gibi net, güven veren metinler kullanın ve OTP/eposta doğrulamayı sadece kurtarma senaryosu olarak bırakın.

Güvenlik ve en iyi uygulamalar

- HTTPS zorunlu; Secure, HttpOnly, SameSite cookie bayraklarını doğru ayarlayın. CSRF için same-site veya token stratejisi uygulayın.

- rpId alan adınızla birebir ilişkili olmalı. Üretimde app.example.com kullanıyorsanız origin tam olarak bu olmalı; ters proxy kullanıyorsanız X-Forwarded-Proto/Host başlıklarını doğru iletin.

- Discoverable credentials (resident keys) açıldığında kullanıcı adı girmeden giriş mümkün olur. Ancak veritabanında kullanıcı başına çoklu credential yönetimini kurgulayın.

- Cihaz kaybı ve kurtarma: Kullanıcının birden fazla passkey ekleyebilmesini sağlayın (telefon, laptop, güvenlik anahtarı). Eski credential’ları listeden kaldırma (revoke) imkanı verin.

- Hata yönetimi: Timeout, NotAllowedError, InvalidStateError gibi hataları kullanıcı dostu mesajlarla ele alın. Geri dönüş yolunda asla parola istemeyin; kurtarma akışını ayrı doğrulamalarla çalıştırın.

Test, uyumluluk ve dağıtım

Geliştirme sırasında Chrome DevTools’taki Virtual Authenticator Environment ile farklı platformları simüle edin. iOS 17+, Android 14+, Windows Hello ve macOS/iCloud Keychain ile pratik testler yapın. Google Password Manager ve iCloud senkronizasyon farklarını (cihazlar arası passkey paylaşımı) göz önünde bulundurun.

Üretime geçerken alan adı stratejinizi belirleyin: rpId olarak kök alan adını (example.com) seçip alt alanlarda tutarlılık sağlayın. CDN ve WAF arkasında origin doğru raporlanıyor mu kontrol edin. İzleme için kayıt/giriş başarı oranı, kullanıcı başına credential sayısı, hataya düşen challenge sayısı gibi metrikler tutun.

Sonuç

Passkey (WebAuthn) ile şifresiz giriş, hem güvenliği yükselten hem de kullanıcı deneyimini sadeleştiren bir yaklaşım. Doğru rpId/origin eşlemesi, sıkı challenge doğrulaması ve sağlam bir oturum yönetimiyle phishing’e dirençli bir kimlik doğrulama katmanı elde edersiniz. Üstelik conditional UI ve discoverable credentials sayesinde “parola” kavramını kullanıcıdan tamamen gizleyerek tek dokunuşla giriş deneyimi sunabilirsiniz. Küçük bir POC ile başlayıp, çoklu credential ve kurtarma senaryolarını da kapsayacak şekilde adım adım genellemek en pragmatik yol olacaktır.

11 Eylül 2025 Perşembe

Passkey (WebAuthn) ile Şifresiz Giriş: Node.js Üzerinden Adım Adım Kurulum ve İpuçları

Passkey (WebAuthn) nedir? Neden şimdi?

Passkey, FIDO2 ve WebAuthn standartlarını temel alan, phishing’e dayanıklı ve kullanıcı dostu bir şifresiz kimlik doğrulama yöntemidir. Tarayıcılar ve işletim sistemleri 2024 itibarıyla passkey’leri yerel olarak destekler hale geldi; 2025’te ise iCloud Anahtar Zinciri, Google Password Manager ve üçüncü parti yöneticiler ile çok cihazlı senkronizasyon yaygınlaştı. Sonuç: Kullanıcılar tek dokunuşla (parmak izi, Face ID, Windows Hello) giriş yapabiliyor, geliştiriciler ise veri ihlallerine açık parola depolama yükünden kurtuluyor.

SEO açısından bakarsak, “şifresiz giriş”, “WebAuthn”, “FIDO2” ve “passkey” gibi terimler özellikle güvenlik ve kullanıcı deneyimi odaklı aramalarda öne çıkıyor. Bu rehberde Node.js ile sıfırdan bir passkey akışını nasıl kurabileceğinizi, istemci ve sunucu tarafındaki kritik ayarları ve üretim ortamında karşılaşabileceğiniz hataları ele alacağım.

Temel mimari ve akış

Kayıt (Registration): Sunucu bir “challenge” üretir, istemci WebAuthn API üzerinden biyometrik/PIN ile bir anahtar çifti oluşturur ve attestation ile sunucuya döner. Sunucu bu veriyi doğrulayıp kullanıcının public key’ini kalıcı olarak kaydeder.

Giriş (Authentication): Sunucu yine bir challenge üretir, istemci kayıtlı credential’ı kullanarak imza (assertion) üretir ve döndürür. Sunucu imzayı public key ile doğrular; eşleşirse oturum açılır.

Hazırlık: Alan, HTTPS ve kütüphaneler

WebAuthn üretimde yalnızca HTTPS üzerinde çalışır (localhost hariç). Relying Party ID (rpId), tarayıcının algıladığı etkin alanla uyuşmalıdır. Örneğin site adresiniz “app.ornek.com” ise rpId “ornek.com” ya da “app.ornek.com” olabilir. Node.js tarafında @simplewebauthn/server veya fido2-lib gibi kütüphaneler doğrulama işini büyük ölçüde kolaylaştırır.

Node.js ile uçtan uca akış (özet)

1) Kayıt için challenge üretin: Kullanıcının henüz passkey’i yoksa sunucu tarafında bir kayıt endpoint’i (ör. /webauthn/registration/options) oluşturun. rp.name, rp.id, user.id (rastgele GUID), user.name ve authenticatorSelection (residentKey: “preferred” veya “required”, userVerification: “preferred”) gibi alanları belirleyin. Challenge’ı sunucu oturumunda saklayın.

2) İstemci tarafında create() çağırın: Tarayıcıda navigator.credentials.create({ publicKey: options }) ile kullanıcıdan biyometrik/PIN onayı alın. Dönüşte attestationObject ve clientDataJSON gelecektir. Bu verileri JSON olarak sunucuya gönderin.

3) Attestation doğrulaması: Sunucuda gelen attestation verisini kütüphaneyle doğrulayın. Başarılıysa credentialId, publicKey (COSE veya JWK), signCount ve AAGUID gibi alanları kullanıcıya bağlı olarak veritabanına kaydedin. Aynı kullanıcıya birden fazla credential tanımlanabilir.

4) Giriş için challenge üretin: /webauthn/authentication/options ile kayıtlı credentialId’leri referans alarak yeni bir challenge üretin. userVerification: “preferred” veya “required” ile MFA benzeri güvenlik seviyesi sağlayabilirsiniz.

5) İstemci tarafında get() çağırın: navigator.credentials.get({ publicKey: requestOptions }) ile kullanıcıdan onay alın. Dönüşte authenticatorData, signature ve clientDataJSON gelir; sunucuya gönderin.

6) Assertion doğrulaması ve oturum: İmza doğrulanırsa oturumu başlatın. JWT veya HttpOnly, Secure, SameSite=strict bir çerezle oturumu yönetin. Replay saldırılarını önlemek için challenge tek kullanımlık olmalı ve kısa süreli (örn. 60 sn) geçerli tutulmalıdır.

Veri modeli: Ne saklamalı?

- Kullanıcı: userId (UUID), email/username, oluşturulma tarihi.

- Credential: userId, credentialId (base64url), publicKey (COSE/JWK), signCount, transports (usb, nfc, ble, internal), aaguid, createdAt.

- Güvenlik: Her doğrulamada signCount karşılaştırması yaparak kopyalanmış authenticator tespitine yardımcı olun (bazı platformlarda sabit kalabilir; kütüphanenin notlarını okuyun).

Üretim ipuçları (Güvenlik ve UX)

- Tam HTTPS: Şifreli bağlantı zorunludur. HSTS etkinleştirilebilir.

- Origin ve rpId uyumu: Hata mesajlarının çoğu burada çıkar. Subdomain değişikliklerinde dikkatli olun.

- Discoverable credentials: Kullanıcı adı öncesi doğrudan passkey ile giriş için residentKey’i “required” yapabilirsiniz. Bu, “şifresiz ve kullanıcı adısız” akış sağlar.

- Conditional UI (Chrome/Safari): Giriş formunuzda kullanıcı adı alanı göstermeden passkey istemek için conditional UI kullanın; özellikle mobilde dönüşüm oranını artırır.

- Oturum yönetimi: HttpOnly + Secure çerez kullanın, SameSite=strict iyidir. Token tabanlı sistemlerde kısa ömürlü access token ve yenileyici mekanizma kurun.

- FallBack ve hesap kurtarma: Yedek kodlar, e-posta linki veya TOTP gibi alternatifleri dengeli biçimde sunun. Amaç passkey’e öncelik verip erişilebilirliği korumaktır.

- Attestation politikası: Çoğu tüketici uygulaması “none” kullanır. Kurumsal gereksinimlerde belirli üreticilere kısıtlama getirmek için attestation “direct” değerlendirilebilir.

- Rate limit ve anti-automation: Kayıt ve giriş uç noktalarınızı hız sınırlayın, bot koruması ekleyin.

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

“The relying party ID is not a registrable domain suffix...” rpId alan adınızla uyuşmuyor olabilir. Geliştirmede localhost kullanın; üretimde tam alan adıyla test edin.

“NotAllowedError” Kullanıcı işlemi iptal etmiş olabilir veya conditional UI tetiklenmemiştir. get()/create() çağrısını kullanıcı etkileşimi (click) bağlamında başlatın.

Attestation doğrulama başarısız Sertifika zinciri veya format hatası olabilir. @simplewebauthn gibi kütüphanelerin güncel sürümünü kullanın; ham binary verileri doğru base64url kodladığınızdan emin olun.

Safari farklılıkları iOS’ta üçüncü parti iframe içinde WebAuthn kısıtlı olabilir. Mümkünse üst alan üzerinde akışı çalıştırın.

Sonuç

Passkey (WebAuthn) ile şifresiz giriş, güvenliği artırırken kullanıcı deneyimini sadeleştirir. Node.js tarafında doğru rpId/origin ayarları, tek kullanımlık challenge’lar, güvenli oturum yönetimi ve iyi bir veri modeli ile üretim seviyesinde sağlam bir akış kurabilirsiniz. 2025 itibarıyla tarayıcı ve işletim sistemi desteği olgunlaştığı için, yeni projelerde parolayı varsayılan kabul etmek yerine passkey’i birincil kimlik doğrulama olarak düşünmek artık pratik ve rekabetçidir. Küçük başlayın, conditional UI ile sürtünmeyi azaltın ve kademeli geçiş stratejisiyle mevcut kullanıcı tabanınızı passkey’e taşıyın.

3.

5 Eylül 2025 Cuma

Passkeys (WebAuthn) ile Şifresiz Giriş: Adım Adım Uygulama Rehberi

Şifrelerle boğuşmanın sonuna gelmek üzereyiz. Passkeys, yani FIDO2/WebAuthn tabanlı şifresiz kimlik doğrulama, hem kullanıcı deneyimini iyileştiriyor hem de oltalama saldırılarına karşı çok daha güçlü bir koruma sağlıyor. Bu rehberde, modern web uygulamalarına passkey desteğini nasıl ekleyebileceğinizi, mimari gereksinimleri ve en iyi uygulamaları sade bir dille anlatıyorum.

Neden Passkeys? Klasik parolalar tahmin edilebilir, tekrar kullanılır ve sızıntılarda kolayca ele geçirilir. Passkeys ise cihaz tabanlı, kök anahtarları donanımda korunan (Secure Enclave/TPM) bir anahtar çifti yaklaşımı kullanır. Özel anahtar cihazda kalır, sunucu yalnızca herkese açık anahtarı saklar. Giriş sırasında sunucu tarafından verilen bir “challenge” imzalanır; bu sayede oltalama siteleri doğru kök bağlamı oluşturamadığı için doğrulama başarısız olur.

Passkey Nedir? Kısa Teknik Özet

Passkeys, WebAuthn API’si ve FIDO2 standartlarının bir birleşimidir. Tarayıcı (veya mobil OS), “platform authenticator” (cihaz üzerindeki biyometri/PIN) ya da “cross-platform authenticator” (USB/NFC güvenlik anahtarı) kullanarak kullanıcıyı doğrular. Uyumlu tarayıcılar: Chrome, Safari, Edge, Firefox (bazı platform kısıtları olabilir). Uyumlu işletim sistemleri: iOS/iPadOS 16+, macOS Ventura+, Android 9+, Windows 10/11 (Güncel) vb.

Mimari ve Gereksinimler

- Zorunlu HTTPS: WebAuthn yalnızca güvenli kökenlerde çalışır. Geliştirme için localhost istisnası vardır.
- Relying Party ID (rpId): Genellikle alan adınız. rpId, kök alanla eşleşmeli ve alt alanlar için doğru yapılandırılmalı.
- Sunucu tarafı saklama: Kullanıcı başına credentialId, publicKey, signCount (veya counter), userHandle gibi alanlar güvenli biçimde saklanmalı.
- Oturum yönetimi: Başarılı doğrulama sonrası session veya JWT üretin. Session sabitleme ve CSRF’ye dikkat edin.

Kayıt (Registration) Akışı

1) Sunucu challenge üretir: Kullanıcı kayıt sayfasında “Passkey oluştur” dediğinde sunucu tek kullanımlık bir challenge (rastgele bayt dizisi) üretir ve front-end’e gönderir. Yanıtınız; rp (name, id), user (id, name, displayName), pubKeyCredParams (örn. -7 ES256), authenticatorSelection (residentKey=required, userVerification=required) gibi parametreleri içermeli.

2) İstemci credential oluşturur: Tarayıcı, navigator.credentials.create({ publicKey: ... }) çağrısıyla cihazın biyometrisi/PIN’i üzerinden kullanıcıyı doğrular ve bir credential üretir. Kullanıcı rızası alınır ve işlem OS düzeyinde güvenlidir.

3) Sunucu doğrular ve kaydeder: İstemciden dönen attestation ve clientDataJSON, sunucuda doğrulanır. Güvenilir bir kütüphane ile (Node.js: @simplewebauthn/server; Java: WebAuthn4J; Python: webauthn) kontrol edebilirsiniz. Başarılıysa credentialId, publicKey ve signCount veritabanına yazılır. Attestation politikasını “none” tutarak gizliliği artırabilir veya kurumsal senaryolarda belirli üreticileri zorunlu kılabilirsiniz.

Giriş (Authentication) Akışı

1) Sunucu challenge üretir: Giriş düğmesine basıldığında sunucu yeni bir challenge üretir ve istemciye gönderir. allowCredentials ile kayıtlı credentialId’leri listeleyebilir veya “discoverable credentials” kullanıyorsanız listeyi boş bırakabilirsiniz.

2) İstemci imza oluşturur: navigator.credentials.get({ publicKey: ... }) çağrısı yapılır. Kullanıcı biyometri/PIN ile onay verir ve cihaz challenge’ı imzalar.

3) Sunucu imzayı doğrular: clientDataJSON ve authenticatorData içindeki rpIdHash, origin, flags (UP, UV), signCount ve signature doğrulanır. counter artışı kontrol edilerek tekrar oynatma (replay) engellenir. Başarılıysa oturum başlatılır.

Senkrone ve Cihaza Bağlı Passkeys

- Senkrone Passkeys: Apple, Google ve Microsoft ekosistemlerinde aynı hesabın bağlı cihazları arasında uçtan uca şifreli senkronizasyon yapılır. Kullanıcı için harika UX, ancak kurumsal ortamlarda veri politikaları gözden geçirilmeli.
- Cihaza Bağlı (Device-bound): Anahtar yalnızca oluşturulduğu cihazda bulunur. Daha sıkı güvenlik isteyen sektörlerde tercih edilir. Gerekirse ikisi bir arada desteklenebilir.

UX İpuçları ve Koşullu UI

- Koşullu UI: Chrome ve Safari, giriş formu odaklandığında otomatik passkey önerisi sunabilir. Bu, “parola yerine passkey” mesajını doğal şekilde yerleştirir.
- Adım adım benimsetme: İlk girişte kullanıcıya “Şifresiz giriş ekle (önerilir)” çağrısı yapın. Zorunlu kılmayın, alternatif bırakın.
- Geri dönüş planı: Kullanıcı cihazını kaybedebilir. E-posta/OTP veya destek kanalını yalnızca hesap kurtarma için sunun; normal girişte passkey’i önceliklendirin.
- Platform/cross-platform seçimi: Dizüstü kullanıcıları için platform authenticator yeterli olabilir; saha ekipleri için güvenlik anahtarları (USB/NFC) mantıklı.

Güvenlik ve Uyum

- Phishing direnci: rpId ve origin eşlemesi, yanlış etki alanıyla giriş yapılmasını engeller.
- Gizlilik: Attestation’ı çoğunlukla “none” tutarak cihaz damgalanmasını önleyin.
- Sertleştime: HSTS, COOP/COEP, güçlü TLS ayarları, zaman senkronizasyonu. Sunucu saat sapması doğrulamayı bozabilir.
- Uyumluluk: En güncel tarayıcı/OS sürümlerini hedefleyin. Eski cihazlar için parola + 2FA yedek planı bulundurun.

Uygulama İskeleti: Hızlı Kontrol Listesi

- Alan adınızı ve rpId’nizi netleştirin, HTTPS zorunludur.
- Veritabanında kullanıcı tablo şemasına credentialId (base64url), publicKey (COSE), signCount, createdAt, lastUsed alanlarını ekleyin.
- Kayıt ve giriş için ayrı endpoint’ler tanımlayın; her ikisi de nonce/challenge üretmeli ve kısa süreli saklamalı.
- Kütüphane seçin: Node.js için @simplewebauthn, Java için WebAuthn4J, Python için webauthn gibi olgun çözümler kullanın.
- Test: Chrome DevTools “Virtual Authenticator” ile farklı senaryoları (resident key, UV required) test edin.
- Telemetri: Başarı/başarısızlık oranlarını, tarayıcı/OS kırılımını izleyin; eğitim içerikleriyle dönüşümü artırın.

Sık Karşılaşılan Hatalar

- origin/rpId uyuşmazlığı: www ve çıplak alanı karıştırmayın; üretimde tek bir kök alan belirleyin.
- HTTP yerine HTTPS: Geliştirme dışında çalışmaz; sertifikayı doğru kurun.
- Yanlış COSE algoritması: Sunucu ve istemci aynı algoritmaları kabul etmeli (ör. ES256).
- Counter tutarsızlığı: signCount geriye düşerse cihaza güveni düşürün ve yeniden kayıt isteyin.

Özetle, passkeys hem güvenlik hem de kullanıcı deneyimi açısından önümüzdeki yılların standardı olacak. Doğru mimariyle kurguladığınızda, kullanıcılarınızın parolaları hatırlamasını istemez, oltalama riskini azaltır ve destek taleplerini düşürürsünüz. Küçük bir PoC ile başlayın, slayt yerine gerçek kullanıcı akışı tasarlayın ve dönüşüm metriklerini yakından takip edin. Bir kez oturduğunda, “Şifremi unuttum” döneminin kapandığını hissedeceksiniz.