FIDO2 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
FIDO2 etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

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.

11 Aralık 2025 Perşembe

Next.js ile WebAuthn (Passkey) Entegrasyonu: Parolasız Giriş Adım Adım

Parolasız kimlik doğrulama, kullanıcı deneyimini iyileştirirken hesap güvenliğini artırmanın en pratik yolu haline geldi. WebAuthn ve Passkey teknolojileri sayesinde kullanıcılar artık SMS kodları veya karmaşık parolalar yerine cihazlarındaki biyometrik sensörlerle giriş yapabiliyor. Bu yazıda, Next.js üzerinde WebAuthn tabanlı Passkey entegrasyonunu adım adım anlatarak, hem teknik detayları hem de üretim ortamı için ipuçlarını paylaşacağım.

Kısaca özetlemek gerekirse, WebAuthn FIDO2 standardının bir parçasıdır ve tarayıcılar aracılığıyla donanımsal (Güvenli Anahtarlar, Touch ID, Windows Hello vb.) veya platform tabanlı kimlik doğrulayıcılarla anahtar çifti üretip doğrulamayı mümkün kılar. RP (Relying Party) ID, origin ve challenge mekanizmaları doğru kurgulandığında, hem phishing dirençli hem de kullanıcı dostu bir giriş deneyimi elde edersiniz.

Önkoşullar ve Mimari

Gerekenler: Node.js 18+, Next.js 13+ (App Router tercihen), HTTPS (yerelde self-signed veya localhost), ve bir sunucu tarafı doğrulama paketi. Toplulukta yaygın kullanılan kütüphanelerden biri @simplewebauthn. Akış şu şekilde işler: Sunucu, kayıt veya giriş için tek kullanımlık bir challenge üretir ve istemciye döner. İstemci, tarayıcıdaki navigator.credentials API’sini (veya sarmalayıcı kütüphane) çağırarak kimlik doğrulayıcıyla işlem yapar ve imzalı yanıtı sunucuya gönderir. Sunucu, public key ve imza doğrulamasıyla işlemi sonuçlandırır.

Kurulum

Yeni bir Next.js projesi oluşturarak başlayalım:

npx create-next-app@latest passkey-demo --typescript
cd passkey-demo
npm i @simplewebauthn/server @simplewebauthn/browser cookie uuid

Basit bir yapı için .env dosyanıza aşağıdaki değerleri ekleyin (yerel geliştirme için):

RP_ID=localhost
RP_NAME=Passkey Demo
ORIGIN=http://localhost:3000

Kayıt (Registration) Akışı

Kullanıcı bir Passkey oluşturmak istediğinde önce sunucudan registration options alır. Bu seçenekler, kimlik doğrulayıcıya hangi parametrelerle anahtar üretmesi gerektiğini söyler. Next.js App Router kullandığınızı varsayarak endpoint’leri şu şekilde düşünebilirsiniz:

// app/api/webauthn/registration/options/route.ts
import { generateRegistrationOptions } from '@simplewebauthn/server';
import { cookies } from 'next/headers';
import { v4 as uuid } from 'uuid';

export async function GET() {
  const userId = uuid(); // Demo için rastgele. Gerçekte gerçek kullanıcı ID'si olmalı.
  const opts = await generateRegistrationOptions({
    rpName: process.env.RP_NAME!,
    rpID: process.env.RP_ID!,
    userID: userId,
    userName: '[email protected]',
    attestationType: 'none',
    authenticatorSelection: {
      residentKey: 'preferred',
      userVerification: 'preferred',
    },
  });

  // Challenge'ı oturumda saklayın
  cookies().set('regChallenge', opts.challenge, { httpOnly: true });

  return new Response(JSON.stringify({ userId, options: opts }), { status: 200 });
}

İstemci tarafında, tarayıcı API’si ile uğraşmayı kolaylaştırmak için @simplewebauthn/browser paketini kullanabiliriz:

// app/register/page.tsx
'use client';
import { startRegistration } from '@simplewebauthn/browser';

export default function Register() {
  const onRegister = async () => {
    const res = await fetch('/api/webauthn/registration/options');
    const { userId, options } = await res.json();
    const attRes = await startRegistration(options);
    await fetch('/api/webauthn/registration/verify', {
      method: 'POST',
      body: JSON.stringify({ userId, attRes }),
    });
    alert('Passkey oluşturuldu!');
  };
  return <button onClick={onRegister}>Passkey Oluştur</button>;
}

Sunucu, istemciden gelen yanıtı doğrulamalıdır. Doğrulama sonunda public key’i ve ilgili metadata’yı kullanıcı profiline kalıcı olarak kaydedersiniz.

// app/api/webauthn/registration/verify/route.ts
import { verifyRegistrationResponse } from '@simplewebauthn/server';
import { cookies } from 'next/headers';

export async function POST(req: Request) {
  const { userId, attRes } = await req.json();
  const expectedChallenge = cookies().get('regChallenge')?.value;

  const verification = await verifyRegistrationResponse({
    response: attRes,
    expectedChallenge,
    expectedOrigin: process.env.ORIGIN!,
    expectedRPID: process.env.RP_ID!,
  });

  if (!verification.verified) return new Response('Doğrulanamadı', { status: 400 });

  // verification.registrationInfo'dan publicKey ve credentialID'yi alıp DB'ye kaydedin
  return new Response('OK', { status: 200 });
}

Giriş (Authentication) Akışı

Girişte benzer şekilde bir challenge üretip istemciye gönderirsiniz. Kullanıcı cihazındaki Passkey ile imzalanan yanıtı sunucu doğrular. Burada kullanıcıya ait kayıtlı credentialID’lerinizi ve public key’lerinizi DB’den çekmeniz gerekir.

// app/api/webauthn/authentication/options/route.ts
import { generateAuthenticationOptions } from '@simplewebauthn/server';
import { cookies } from 'next/headers';

export async function GET() {
  const opts = await generateAuthenticationOptions({
    rpID: process.env.RP_ID!,
    userVerification: 'preferred',
  });
  cookies().set('authChallenge', opts.challenge, { httpOnly: true });
  return new Response(JSON.stringify({ options: opts }), { status: 200 });
}
// app/login/page.tsx
'use client';
import { startAuthentication } from '@simplewebauthn/browser';

export default function Login() {
  const onLogin = async () => {
    const res = await fetch('/api/webauthn/authentication/options');
    const { options } = await res.json();
    const assertion = await startAuthentication(options);
    await fetch('/api/webauthn/authentication/verify', {
      method: 'POST',
      body: JSON.stringify({ assertion }),
    });
    alert('Giriş başarılı!');
  };
  return <button onClick={onLogin}>Passkey ile Giriş</button>;
}
// app/api/webauthn/authentication/verify/route.ts
import { verifyAuthenticationResponse } from '@simplewebauthn/server';
import { cookies } from 'next/headers';

// Not: Burada kullanıcıya ait credential'ları DB'den çekmelisiniz.
export async function POST(req: Request) {
  const { assertion } = await req.json();
  const expectedChallenge = cookies().get('authChallenge')?.value;

  const verification = await verifyAuthenticationResponse({
    response: assertion,
    expectedChallenge,
    expectedOrigin: process.env.ORIGIN!,
    expectedRPID: process.env.RP_ID!,
    authenticator: {
      credentialID: Buffer.from('...'), // DB'den
      credentialPublicKey: Buffer.from('...'), // DB'den
      counter: 0,
    },
  });

  if (!verification.verified) return new Response('Hatalı kimlik doğrulama', { status: 401 });
  return new Response('OK', { status: 200 });
}

Üretime Hazırlık: İpuçları ve En İyi Uygulamalar

- HTTPS zorunlu: WebAuthn, localhost harici kökenlerde güvenli bağlam ister. Prod ortamda gerçek sertifika kullanın.

- RP ID ve Origin uyumu: RP_ID alan adınızla, ORIGIN ise protokol ve host’la birebir eşleşmeli. Alt alan adları ve çoklu çevrelerde yanlış yapılandırma en yaygın hatadır.

- Challenge ve oturum: Challenge değerini kısa ömürlü ve kullanıcıya bağlı saklayın. CSRF ve yeniden oynatma saldırılarına karşı dikkatli olun.

- Kullanıcı deneyimi: Platform authenticator (cihaz içi) ve cross-platform (USB/NFC) anahtarları desteklediğinizden emin olun. Cihaz değişimlerinde çoklu Passkey veya hesap kurtarma akışları tasarlayın.

- Günlükleme ve ölçüm: Başarısız doğrulama nedenlerini (origin uyuşmuyor, RP ID yanlış, kullanıcı doğrulaması başarısız vb.) log’layın; destek taleplerini azaltır.

Sonuç

WebAuthn ve Passkey ile parolasız kimlik doğrulama, hem saldırı yüzeyini küçültür hem de kullanıcı memnuniyetini artırır. Next.js üzerinde @simplewebauthn ile kurulum oldukça hızlıdır: kayıt ve giriş için challenge kurgusu, doğru RP/Origin ayarı ve güvenli oturum yönetimi yapı taşlarını oluşturur. Bu mimariyi uygulayarak uygulamanızda modern, phishing dirençli ve yüksek dönüşüm oranına sahip bir giriş deneyimine geçiş yapabilirsiniz.

3 Aralık 2025 Çarşamba

Next.js ile Passkey (WebAuthn) Entegrasyonu: Parolasız Girişe Adım Adım Rehber

Giriş: Neden Passkey (WebAuthn)?

Parolalar hem kullanıcılar hem de geliştiriciler için baş ağrısı. Zayıf parolalar, kimlik avı, sızıntılar ve unutma problemi derken, güvenli ve sorunsuz bir deneyim için endüstri Passkey (FIDO2/WebAuthn) standartına hızla geçiyor. Passkey ile kullanıcılar biyometri (Face ID, Touch ID), donanım güvenlik anahtarı veya cihaz PIN’iyle güvenli ve parolasız giriş yapabiliyor. Bu rehberde, Next.js ve simplewebauthn kullanarak uçtan uca bir Passkey akışını nasıl kurabileceğinizi adım adım anlatıyorum.

Gereksinimler ve Kurulum

Başlamadan önce Node.js 18+, Next.js 13/14 App Router, bir veri tabanı (PostgreSQL veya MongoDB) ve HTTPS (localhost için Chrome’da güvenilir sertifika veya bir tünel aracı) gerekli. WebAuthn, origin ve rpID değerlerine duyarlıdır; yerel geliştirmede localhost ve üretimde gerçek alan adını kullanın. Kütüphaneler için npm i @simplewebauthn/server @simplewebauthn/browser komutunu çalıştırın.

Mimari: Kayıt ve Giriş Akışı

Passkey iki ana akıştan oluşur: Kayıt (Registration) ve Doğrulama (Authentication). Kayıtta sunucu bir challenge üretir, istemci bu veriyi cihazın güvenli donanımına kaydeder ve attestation verisini sunucuya geri yollar. Girişte ise sunucu yeni bir challenge üretir, istemci cihazı bunu imzalar ve imzalı assertion sunucuda doğrulanır. Tüm süreçte challenge değerini oturum (session, Redis) gibi geçici ve güvenli bir yerde tutmak önemlidir.

Sunucu Tarafı: Endpoints ve Doğrulama

Next.js App Router’da app/api altında iki çift endpoint tanımlayın: /register/generate ve /register/verify, /login/generate ve /login/verify. @simplewebauthn/server içindeki generateRegistrationOptions, verifyRegistrationResponse, generateAuthenticationOptions ve verifyAuthenticationResponse yardımcıları işinizi hızlandırır.

Önemli alanlar: rpID alan adınız (ör. example.com), origin tam kök adresiniz (ör. https://example.com). Üretimde bunların sabit ve doğru olması gerekir. Kayıt doğrulandıktan sonra veritabanında şu alanları saklayın: kullanıcı kimliği, credential ID (base64url), publicKey, counter, transports, backupEligibility/backupState bilgileri. Girişte doğrulama sonrası karşılaştırma için counter değerini güncelleyerek yeniden oynatma saldırılarını engelleyin.

İstemci Tarafı: Tarayıcı API’leriyle Etkileşim

Tarayıcı tarafında @simplewebauthn/browser kütüphanesinin startRegistration ve startAuthentication fonksiyonlarını kullanın. Kayıt için önce /register/generate endpoint’inden seçenekleri alın, startRegistration çağrısını yapın ve sonucu /register/verify’e gönderin. Giriş için benzer şekilde /login/generate → startAuthentication → /login/verify akışını izleyin. Bu işlemler sırasında kullanıcı, cihazında biyometrik doğrulama veya güvenlik anahtarına dokunuş gibi bir etkileşimle süreci tamamlar.

Pratik İpuçları ve Sık Hatalar

- Origin/RP ID uyuşmazlığı: En yaygın hata budur. Geliştirmede https://localhost:3000 origin ile rpID=localhost kullanın. Üretimde https://alanadiniz.com ve rpID=alanadiniz.com şart.

- Challenge saklama: Challenge’ı oturumda tutmazsanız doğrulama başarısız olur. Kısa ömürlü bir store (Redis, Signed Cookie) güvenlidir.

- Discoverable credentials: Kullanıcının e-posta girmeden giriş yapabilmesi için resident keys (discoverable) açılabilir. Gizlilik ve UX dengesini iyi düşünün; bazı senaryolarda kullanıcı kimliğini yine de isteyebilirsiniz.

- Platform desteği: iOS/Android, Chrome/Safari/Edge yeni sürümlerde destekler iyi durumdadır; ancak eski cihazlarda güvenlik anahtarı (YubiKey) fallback’i planlayın.

Güvenlik ve Uyum Notları

WebAuthn, kimlik avını ciddi ölçüde azaltır; çünkü imza domain’e (origin) bağlıdır. Yine de bazı ek önlemler gerekir: her istek için CSRF koruması, üretimde HTTPS zorunluluğu, gelen yanıtlar için origin doğrulaması, güvenli cookie ayarları (HttpOnly, SameSite=Lax/Strict, Secure). Kullanıcının birden fazla cihazda passkey kullanabilmesi için hesap başına birden fazla credential kaydına izin verin ve kolay yönetim ekranları oluşturun.

Kurumsal ortamlarda enforce MFA ve politika tabanlı kayıt akışlarını düşünebilirsiniz. Ayrıca, backup/icloud passkey senkronizasyonu devredeyse, cihaz değişiminde kullanıcı deneyimi daha pürüzsüz olur. Bu arada, userVerification modunu required olarak ayarlamak, cihazda biyometrik/PIN doğrulamasını zorunlu kılarak güvenliği artırır.

Örnek Veri Modeli ve Loglama

Basit bir credential tablosu şu alanları içerebilir: id, userId, credentialId (unique), publicKey, counter, deviceType (platform/cross-platform), backupState, transports, createdAt, lastUsedAt. Her doğrulamada lastUsedAt ve counter değerlerini güncelleyin. Üretimde başarısız doğrulamalar için detaylı ancak kişisel veriyi ifşa etmeyen loglar tutun; PII saklamamaya özen gösterin.

Performans ve UX İyileştirmeleri

İlk boyamada kullanıcıya cihazın passkey desteklediğini hızlıca göstermek için PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() ile bir özellik kontrolü yapabilirsiniz. Desteklenmiyorsa alternatif girişi (OTP/Magic Link) otomatik önerin. SSR yerine istemci tarafında akışı tetikleyip, istekleri mutate eden bir data fetching yaklaşımı (SWR/React Query) ile ağ hatalarında kullanıcıya net geri bildirim sağlayın.

Sonuç

Passkey (WebAuthn) entegrasyonu, hem güvenliği hem de dönüşüm oranlarını artıran çağdaş bir yaklaşım. Next.js ve simplewebauthn ile kurulum nispeten hızlı; kritik nokta ise rpID/origin doğruluğu, challenge yönetimi ve credential saklama stratejisi. Bu rehberdeki adımları izleyerek parolasız deneyimi projenize ekleyebilir, kullanıcılarınıza modern ve güvenli bir giriş akışı sunabilirsiniz.

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.

25 Kasım 2025 Salı

Passkey ve WebAuthn ile Parolasız Giriş: Adım Adım Entegrasyon Rehberi (2025)

WebAuthn ve Passkey Nedir, Neden Önemli?

Parola yorgunluğu ve oltalama saldırıları, modern uygulamalar için en büyük güvenlik sorunlarından biri. WebAuthn (W3C standardı) ve FIDO2 ile gelen passkey yaklaşımı, kriptografik anahtarlar kullanarak parolasız ve oltalama dirençli oturum açmayı mümkün kılar. Kullanıcılar cihazlarındaki biyometrik doğrulama (Face ID, Touch ID, Windows Hello) veya güvenlik anahtarı (YubiKey) ile giriş yapar. 2025 itibarıyla Chrome, Safari ve Firefox, platformlar arası passkey senkronizasyonunu (iCloud Anahtarlık, Google Password Manager, 1Password) yaygın biçimde destekliyor.

Temel Kavramlar

Relying Party (RP) ID: Genellikle alan adınızdır (ör. example.com). HTTPS zorunludur ve RP ID ile domain eşleşmelidir.

Authenticator: Kimlik doğrulayıcı cihaz. Platform (cihazın kendi biyometri/TPM’i) veya roaming (USB/NFC/BLE güvenlik anahtarı) olabilir.

Attestation ve Assertion: Kayıt (credential üretimi) ve giriş (imzalı kanıt) aşamalarında tarayıcı ile sunucu arasında değiş tokuş edilen verilerin adlarıdır.

Discoverable Credentials (Resident Keys): Kullanıcının kullanıcı adı yazmadan sadece cihaz doğrulamasıyla oturum açmasına olanak tanır; passkey deneyiminin kalbidir.

Entegrasyon Mimarisi ve Akış

WebAuthn, istemci (tarayıcı) ve sunucu arasında iki ana akış tanımlar: (1) Kayıt ve (2) Giriş. Tipik uç noktalar: /webauthn/register/options (sunucu challenge üretir), /webauthn/register/verify (sunucu attestation doğrular), /webauthn/login/options (sunucu challenge üretir), /webauthn/login/verify (sunucu assertion doğrular). Sunucu tarafında kullanıcıya ait credentialID, publicKey (COSE formatında), signCount, transports ve isteğe bağlı userHandle kalıcı olarak saklanır.

Gereksinimler ve Dikkat Edilecekler

- Uygulamanız HTTPS üzerinde çalışmalı. Lokal geliştirme için localhost istisnası var, ancak üretimde sertifika zorunlu.
- RP ID, alt alan adları ile farklılık gösterebilir. Örneğin app.example.com için RP ID’yi example.com seçerseniz, alt alanlar arasında passkey paylaşımı kolaylaşır.
- Sunucuda doğru algoritma setini (ES256 gibi) destekleyin.
- Origin ve RP ID mutlak doğrulanmalı; aksi halde güvenlik modeli bozulur.
- signCount (veya signature counter) replay tespitinde kullanılmalıdır.

Uygulama Örneği: Sunucu ve İstemci

Sunucu teknolojisi fark etmeksizin yaklaşım aynıdır. Node.js için @simplewebauthn/server, tarayıcı tarafı için @simplewebauthn/browser; Java için webauthn4j; .NET için Fido2NetLib yaygın kütüphanelerdir.

Kayıt adımları: 1) Kullanıcı oturum açmış veya e-posta doğrulamış olmalı. 2) Sunucu challenge üretir, rp (name, id), user (id, name), pubKeyCredParams, authenticatorSelection (residentKey=required, userVerification=preferred/required) gibi alanlarla tarayıcıya döner. 3) Tarayıcı navigator.credentials.create({ publicKey: ... }) çağırır. 4) Tarayıcıdan dönen attestation, sunucuda doğrulanır; geçerliyse publicKey kaydedilir.

Giriş adımları: 1) Sunucu challenge üretir ve allowCredentials (istemciye bağlı ise opsiyonel) ile döner. 2) Tarayıcı navigator.credentials.get({ publicKey: ... }) çağırır. 3) Dönen assertion, imza ve authenticatorData sunucuda doğrulanır; signCount güncellenir ve oturum açılır.

Passkey UX İpuçları ve Conditional UI

Modern tarayıcılarda “Conditional UI” desteğiyle, kullanıcı adı alanı odaklanmadan dahi passkey önerisi açılabilir. Tarayıcı tarafında mediation: "conditional" kullanımı, şifre doldurma ile tutarlı bir deneyim sunar. Özellikle mobilde autofill entegrasyonu dönüşüm oranlarını artırır. “Kullanıcı adı olmadan giriş” senaryosu için “discoverable credentials” etkin olmalıdır.

Cihazlar Arası Senkronizasyon ve Kurtarma

Passkey’ler iCloud Keychain, Google Password Manager veya destekleyen parola kasalarında şifrelenmiş biçimde senkronize olabilir. Kullanıcılara en az bir roaming güvenlik anahtarı veya alternatif kurtarma yöntemi önerin. SMS/e-posta yedekleri zorunlu olmamalı; mümkünse TOTP veya ek bir passkey kaydı sağlayın.

Güvenlik ve Uyum

- Attestation politikanızı belirleyin: “none” çoğu tüketici uygulaması için yeterli, kurumsal ortamda AAGUID bazlı kısıtlama gerekebilir.
- Phishing dirençli olması, RP ID sabitlemesi ve kullanıcı doğrulaması (UV) ile sağlanır.
- Rate limiting, origin checking ve replay protection uygulayın.
- Log’larda özel anahtar yer almaz; yalnızca publicKey ve metadata saklanır.

Test, Hata Ayıklama ve Yayına Alma

Geliştirme sürecinde Chrome’un Virtual Authenticator panelini (chrome://webauthn) kullanarak farklı cihaz senaryolarını simüle edebilirsiniz. Staging ortamında gerçek cihazlarla (iOS Safari, Android Chrome, Windows Hello) çapraz test yapın. CDN veya ters proxy arkasında origin/RP ID uyuşmazlıklarına dikkat edin. Son aşamada parola ile hibrit oturum açma bir süre daha açık tutulabilir; ardından parolayı kademeli kaldırma stratejisi izlenebilir.

Sonuç

WebAuthn ve passkey, kullanıcı deneyimini iyileştirirken güvenliği ciddi biçimde artırır. Doğru RP ID, sıkı origin doğrulaması, güvenilir kütüphaneler ve iyi bir kurtarma politikası ile entegrasyon sorunsuz ilerler. Bugün küçük bir pilot başlatıp kullanıcılarınızın en çok kullandığı platformlarda test ederek geçişi adım adım hızlandırabilirsiniz.

22 Kasım 2025 Cumartesi

WebAuthn ve Passkey ile Parolasız Kimlik Doğrulama: Adım Adım Uygulama Rehberi

WebAuthn ve Passkey Nedir? Neden Önemli?

Parolalar güvenliğin en zayıf halkası olmaya devam ediyor: sızıntılar, kimlik avı, parola tekrar kullanımı ve sosyal mühendislik riski her zamankinden yüksek. WebAuthn (W3C) ve FIDO2 standardı, kullanıcıların cihazlarını (telefon, güvenlik anahtarı, bilgisayar) bir Passkey olarak kullanmasını sağlayarak parolasız, kimlik avına dayanıklı ve kullanıcı dostu bir kimlik doğrulama sunar. Bu yazıda, modern bir web uygulamasında WebAuthn ve Passkey ile parolasız kimlik doğrulamayı adım adım nasıl kuracağınızı anlatıyorum.

Mimari ve Akışın Özeti

WebAuthn iki temel akışa dayanır: kayıt (registration) ve giriş (authentication). Kayıt sırasında sunucu bir “challenge” üretir, tarayıcı ve cihaz bu challenge’ı cihaza özgü özel anahtarla imzalar ve sunucu bu kaydı güvenli şekilde saklar. Girişte yine challenge üretilir ve kullanıcı cihazıyla imza atar; sunucu saklanan genel anahtar ile imzayı doğrular. Bu süreçte kullanıcı deneyimi Touch ID/Face ID, Windows Hello veya bir güvenlik anahtarı dokunuşu kadar basittir.

Önkoşullar ve Dikkat Edilecekler

- HTTPS zorunludur (localhost hariç).
- RP ID (Relying Party ID) genellikle alan adınızdır (ör. example.com).
- Passkey senkronizasyonu için kullanıcılar Apple/Google/Microsoft hesabına giriş yapmış olabilir; güvenlik anahtarı (roaming authenticator) ile de çalışır.
- Tarayıcı desteği modern tarayıcılarda çok iyi; mobilde de yaygın.

Sunucu Tarafı: Challenge Üretimi ve Doğrulama

Sunucuda iki uç nokta gerekir: kayıt için “options” ve “verify”, giriş için “options” ve “verify”. Node.js dünyasında @simplewebauthn/server popüler ve güvendiğim bir çözümdür. Aşağıda yalın bir örnek görebilirsiniz.

// npm i @simplewebauthn/server express cors
import express from 'express';
import cors from 'cors';
import {
  generateRegistrationOptions,
  verifyRegistrationResponse,
  generateAuthenticationOptions,
  verifyAuthenticationResponse,
} from '@simplewebauthn/server';

const app = express();
app.use(cors());
app.use(express.json());

const rpID = 'example.com';
const rpName = 'Örnek Uygulama';
const db = { users: new Map() }; // { userId: { id, username, credentials: [] } }

app.post('/webauthn/register/options', (req, res) => {
  const { userId, username } = req.body;
  const user = db.users.get(userId) || { id: userId, username, credentials: [] };
  const opts = generateRegistrationOptions({
    rpID,
    rpName,
    userID: user.id,
    userName: user.username,
    attestationType: 'none',
    excludeCredentials: user.credentials.map(c => ({ id: c.credentialID, type: 'public-key' })),
    authenticatorSelection: { residentKey: 'required', userVerification: 'required' },
  });
  user.currentChallenge = opts.challenge;
  db.users.set(userId, user);
  res.json(opts);
});

app.post('/webauthn/register/verify', async (req, res) => {
  const { userId, attResp } = req.body;
  const user = db.users.get(userId);
  const verification = await verifyRegistrationResponse({
    response: attResp,
    expectedChallenge: user.currentChallenge,
    expectedRPID: rpID,
    expectedOrigin: 'https://example.com',
  });
  if (verification.verified) {
    const { credentialPublicKey, credentialID, counter } = verification.registrationInfo;
    user.credentials.push({ credentialID, credentialPublicKey, counter });
    db.users.set(userId, user);
  }
  res.json({ ok: verification.verified });
});

app.post('/webauthn/auth/options', (req, res) => {
  const { userId } = req.body;
  const user = db.users.get(userId);
  const opts = generateAuthenticationOptions({
    rpID,
    userVerification: 'required',
    allowCredentials: user.credentials.map(c => ({ id: c.credentialID, type: 'public-key' })),
  });
  user.currentChallenge = opts.challenge;
  db.users.set(userId, user);
  res.json(opts);
});

app.post('/webauthn/auth/verify', async (req, res) => {
  const { userId, authResp } = req.body;
  const user = db.users.get(userId);
  const verification = await verifyAuthenticationResponse({
    response: authResp,
    expectedChallenge: user.currentChallenge,
    expectedRPID: rpID,
    expectedOrigin: 'https://example.com',
    authenticator: user.credentials.find(c => c.credentialID.equals(Buffer.from(authResp.rawId, 'base64url'))),
  });
  res.json({ ok: verification.verified });
});

app.listen(3000);

Ön Uç: Tarayıcıda Kayıt ve Giriş

Tarayıcı API’si navigator.credentials üzerinden çalışır. Dönüş tipleri ArrayBuffer içerdiğinden Base64URL dönüşümleri gerekir. Basitlik için @github/webauthn-json veya @simplewebauthn/browser kullanabilirsiniz.

// npm i @simplewebauthn/browser
import {
  create as webauthnCreate,
  get as webauthnGet,
} from '@simplewebauthn/browser';

async function registerPasskey(userId, username) {
  const opts = await fetch('/webauthn/register/options', {
    method: 'POST', headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ userId, username }),
  }).then(r => r.json());

  const attResp = await webauthnCreate({ publicKey: opts });
  const verify = await fetch('/webauthn/register/verify', {
    method: 'POST', headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ userId, attResp }),
  }).then(r => r.json());

  return verify.ok;
}

async function loginWithPasskey(userId) {
  const opts = await fetch('/webauthn/auth/options', {
    method: 'POST', headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ userId }),
  }).then(r => r.json());

  const authResp = await webauthnGet({ publicKey: opts });
  const verify = await fetch('/webauthn/auth/verify', {
    method: 'POST', headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({ userId, authResp }),
  }).then(r => r.json());

  return verify.ok;
}

Güvenlik ve UX İpuçları

- Kullanıcı doğrulamasını “required” tutun; cihaz biyometri veya PIN ister.
- Passkey’i birincil giriş yöntemi yapın, parolayı opsiyonel geri dönüş kanalı olarak değerlendirin.
- Aynı kullanıcı için birden fazla autentikatör kaydına izin verin (telefon, laptop, güvenlik anahtarı).
- Cihaz değiştirmede QR ile “cihazlar arası” passkey oturumu deneyimini etkinleştirin (Chrome/Safari destekler).
- Kaydı tamamlamadan önce challenge ve RP ID eşleşmelerini mutlaka doğrulayın.

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

- origin ve rpID eşleşmiyor: HTTPS alan adınız ile RP ID aynı olmalı (subdomain farklarına dikkat).
- Base64URL dönüşümleri eksik: webauthn-json veya simplewebauthn/browser kullanın.
- localhost testi: http://localhost için istisna var, ancak 127.0.0.1 farklı kabul edilebilir; tutarlı kullanın.
- allowCredentials boş: Kullanıcının kayıtlı credential listesini girişte doğru döndürdüğünüzden emin olun.

Sonuç

WebAuthn ve Passkey ile parolasız kimlik doğrulama artık niş bir teknoloji değil; büyük tarayıcılar ve platformlarca olgun şekilde destekleniyor. Doğru kütüphanelerle kurulum süreci şaşırtıcı derecede kısa, güvenlik kazanımı ise çok büyük. Ürününüzde parolaları azaltmak ve kimlik avına dayanıklı, modern bir deneyim sunmak istiyorsanız, bugün küçük bir POC ile başlayın ve kullanıcı tabanınıza kademeli olarak yayınlayın.

21 Kasım 2025 Cuma

Passkeys (FIDO2/WebAuthn) ile Şifresiz Kimlik Doğrulama: Adım Adım Uygulama Rehberi

Passkey nedir ve neden şimdi?

Parola yorgunluğu, kimlik avı ve bot saldırıları modern uygulamaların en büyük tehditlerinden. Passkey, FIDO2 ve WebAuthn standartlarına dayanan, parolasız ve kimlik avına dirençli bir doğrulama yaklaşımıdır. Kullanıcı, cihazındaki biyometri (parmak izi, Face ID) veya PIN ile giriş yapar; tarayıcı, cihazda üretilen özel anahtarı kullanır ve sunucuya sadece genel anahtar gider. Böylece veri ihlallerinde çalınacak parola kalmaz.

Mimariyi bir bakışta anlayın

WebAuthn istemci tarafı (tarayıcı ve platform autentikatörü) ile sunucu arasında çalışır. Kayıtta, sunucu bir “challenge” üretir; tarayıcı bu challenge’ı cihazın güvenli çipinde üretilen özel anahtar ile imzalar ve sunucuya genel anahtar + imza döner. Girişte de benzer şekilde geçici bir challenge imzalanır. Sunucu, daha önce sakladığı genel anahtar ile imzayı doğrular ve kullanıcıyı oturum açmış sayar.

Önkoşullar ve planlama

1) Alan adınız için HTTPS zorunludur. 2) Sunucu tarafında WebAuthn doğrulama yapabilecek bir kütüphane seçin (örn. dilinize uygun FIDO2/WebAuthn paketleri). 3) Kullanıcı akışını planlayın: önce passkey kaydı, ardından giriş. 4) Çoklu cihaz senaryosunu düşünün: senkronize passkey (Apple/Google ekosistemleri) ve güvenlik anahtarlarını (YubiKey vb.) desteklemek isteyebilirsiniz.

Kayıt (Registration) akışı

Adım 1: Sunucu, kullanıcı için bir kayıt challenge’ı ve RP (Relying Party) bilgilerini üretir. Adım 2: Tarayıcıda WebAuthn API’sini çağırarak cihazın bir anahtar çifti oluşturmasını istersiniz. Adım 3: Kullanıcı biyometri veya cihaz PIN’i ile onay verir. Adım 4: Tarayıcı, oluşturulan genel anahtarı, attestation ve ilgili meta verileri sunucuya gönderir. Adım 5: Sunucu, gelen veriyi doğrular; geçerli ise kullanıcı hesabına bu genel anahtarı bağlar. Bu aşamadan sonra kullanıcı, parolasız giriş yapabilecek duruma gelir.

Giriş (Authentication) akışı

Adım 1: Sunucu, giriş yapmak isteyen kullanıcı için bir challenge üretir ve tarayıcıya yollar. Adım 2: Tarayıcı, cihazda saklı özel anahtarı kullanarak challenge’ı imzalar; kullanıcı yine biyometri veya PIN ile onay verir. Adım 3: İmzalı veri sunucuya döner. Adım 4: Sunucu, ilgili genel anahtar ile imzayı doğrular ve başarılıysa oturumu başlatır. Tüm süreçte parola veya tek seferlik SMS kodu gerekmez.

Sunucu tarafı doğrulama ipuçları

Doğrulamada RP ID, origin ve challenge eşleşmelerine dikkat edin. Signature counter (sign count) değerini izleyerek olası anahtar klonlama şüphesini tespit edin. Mümkünse attestation doğrulamasını aktif edin ve yalnızca güvenilir üreticilerin autentikatörlerine izin verin. Kullanıcı başına birden çok passkey kaydını desteklemek, hesap kurtarma ve cihaz değişimi için hayat kurtarır.

Kullanıcı deneyimi: Mikro kılavuz

Kullanıcıları “Parolasız giriş” kavramına kısa bir açıklama ile hazırlayın. Kayıtta hangi yöntemlerin desteklendiğini (cihazın dahili biyometrisi, harici güvenlik anahtarı) net ifade edin. Giriş ekranında “Passkey ile devam et” butonu görünür olmalı; alternatif olarak e-posta ile büyülü bağlantı (magic link) veya yedek kodlar ikinci seçenek olarak sunulabilir. Cihaz desteklemiyorsa anlaşılır hata mesajları verin ve geçici olarak SMS/OTP gibi yöntemlere yönlendirin.

Güvenlik en iyi uygulamalar

- HTTPS her ortamda zorunlu. - CSRF ve oturum sabitleme saldırılarına karşı koruma sağlayın. - Rate limiting ve IP itibar kontrolleri ekleyin. - Kademeli yayına geçin: önce beta kullanıcıları ile test, sonra genelleme. - Attestation politikasını, regülasyon gerekliliklerine (ör. finans, sağlık) uyacak şekilde ayarlayın.

Uyumluluk ve tarayıcı desteği

Modern Chromium, Safari ve Firefox tarayıcıları WebAuthn’ı destekliyor. Mobilde iOS ve Android tarafında platform autentikatörleri olgunlaştı. Eski cihazlarda destek kısıtlı olabilir; bu nedenle özelliği feature detection ile koşullu olarak göstermek iyi bir pratik. Ayrıca kurumsal ağlarda güvenlik anahtarlarını tercih eden ekipler için USB/NFC/Bluetooth seçeneklerini dökümante edin.

Performans ve ölçüm

Kayıt ve giriş sürelerini ölçün; özellikle challenge üretimi ve sunucu doğrulama gecikmelerini izleyin. Hata oranlarını, başarısız biyometri denemelerini ve cihaz uyumluluk dağılımını panolara taşıyın. A/B testleri ile “passkey öncelikli” akışların dönüşüm oranlarını kıyaslayın; genellikle ilk oturum açma süreleri ve tekrar girişler belirgin şekilde hızlanır.

Geçiş stratejisi ve hesap kurtarma

Var olan parola tabanlı sisteme passkey eklerken kademeli geçiş önerilir. Önce iki faktör olarak ekleyin, ardından parolasız moda yükseltin. Hesap kurtarma için ikinci e-posta, güvenlik anahtarı veya doğrulanmış cihazda QR onayı gibi seçenekler hazırlayın. Parola sıfırlama sürecini, passkey kayıtlarını koruyacak şekilde yeniden tasarlayın ve her kritik adımda ek onay isteyin.

Sonuç

Passkeys, parolaların zayıflıklarını ortadan kaldıran, kullanıcı dostu ve güvenliği yüksek bir çözüm sunuyor. Doğru akış tasarımı, sıkı sunucu doğrulaması ve temiz bir UX ile WebAuthn’ı uygulamanıza eklemek düşündüğünüzden daha hızlı olabilir. Bugün küçük bir kullanıcı grubunda başlatın, metrikleri izleyin ve parolasız geleceğe emin adımlarla geçin.

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.

8 Kasım 2025 Cumartesi

WebAuthn Passkey Entegrasyonu: Parolasız Giriş Nasıl Eklenir? (Adım Adım Rehber)

Passkey Nedir ve Neden Önemli?

Parolalar hem kullanıcılar hem de geliştiriciler için sorunlu: Zayıf şifreler, phishing saldırıları ve tekrar kullanım derken, güvenlik açıkları kaçınılmaz hale geliyor. Passkey (FIDO2/WebAuthn tabanlı parolasız kimlik doğrulama) bu tabloyu değiştiriyor. Kullanıcılar cihazlarının biyometrik doğrulamasıyla (Face ID, Touch ID, Windows Hello vb.) giriş yapıyor; sunucu tarafında ise yalnızca herkese açık anahtar saklanıyor. Bu yaklaşım phishing’e dirençli, kullanıcı deneyimi açısından zahmetsiz ve uzun vadede bakım maliyetini düşürüyor.

Mimari: Kısa Bir Genel Bakış

WebAuthn, iki ana akışa dayanır: kayıt (registration) ve giriş (authentication). Kayıt akışında sunucu, istemciye bir challenge ve parametreler gönderir; tarayıcı navigator.credentials.create() ile cihaz üzerinde bir anahtar çifti üretir ve herkese açık anahtarı sunucuya geri yollar. Giriş akışında ise sunucu challenge üretir, istemci navigator.credentials.get() ile imza alır ve sunucu bunu doğrular. Tüm süreçte parolayı ne ilettiğinizi ne de sakladığınızı düşünmeniz gerekmez.

Gereksinimler ve Dikkat Edilmesi Gerekenler

- Uygulamanızın HTTPS üzerinde çalışması gerekir (localhost hariç).
- RP ID alanı, genellikle alan adınızın köküdür (ör. example.com). Alt alanlar için doğru RP ID seçimi önemlidir.
- Tarayıcı ve platform desteği oldukça geniştir; yine de eski cihazları hedefliyorsanız geriye uygun bir strateji belirleyin.
- Passkey’lerin cihazlar arası senkronizasyonu (ör. iCloud Anahtar Zinciri, Google Password Manager) kullanıcı deneyimini iyileştirir, ancak kurumsal ortamlarda harici güven anahtarlarını da (security key) desteklemek isteyebilirsiniz.

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

1) Kullanıcı yeni hesap oluşturmak veya hesabına passkey eklemek istediğinde, sunucu bir challenge üretir ve publicKeyCredentialCreationOptions nesnesini oluşturur. Bu nesnede rp (adı ve id), user (id, name, displayName), pubKeyCredParams (COSE algoritmaları), authenticatorSelection (ör. residentKey, userVerification), timeout ve gerekiyorsa attestation alanları yer alır.

2) İstemci tarafında tarayıcıya navigator.credentials.create({ publicKey }) çağrısı yaptırılır. Kullanıcı biyometrik doğrulama ile onaylar. Tarayıcı size id, rawId, response.attestationObject ve response.clientDataJSON döndürür.

3) Sunucu bu verileri doğrular: clientDataJSON içindeki challenge, type ve origin kontrol edilir; attestationObject içinden sertifika zinciri ve anahtar bilgisi çıkarılır. Sonuçta kullanıcı kaydı için credential ID, public key ve signCount veritabanına kaydedilir.

4) Attestation politikanızı belirleyin: Çoğu tüketici uygulaması için none yeterlidir. Düzenlemeye tabi sektörlerde (finans, sağlık) cihaz kanıtı (attestation) şartları farklı olabilir.

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

1) Kullanıcı “Giriş Yap” dediğinde sunucu bir challenge üretir ve publicKeyCredentialRequestOptions oluşturur. Bu nesnede challenge, timeout, rpId ve varsa allowCredentials bulunur.

2) İstemci navigator.credentials.get({ publicKey }) çağrısı yapar. Tarayıcı kullanıcı doğrulamasını ister ve size id, rawId, response.authenticatorData, response.clientDataJSON, response.signature ve mümkünse userHandle döndürür.

3) Sunucu doğrulama yapar: clientDataJSON içindeki challenge ve origin kontrol edilir; authenticatorData içinden RP ID hash, bayraklar ve sayaç (signCount) okunur. signature, veritabanına kaydettiğiniz herkese açık anahtarla doğrulanır. Sayaç ileri gitmiyorsa tekrar kullanım şüphesiyle oturumu reddedin veya riske göre ek doğrulama isteyin.

Discoverable Credentials ve Kullanıcı Deneyimi

Passkey’lerin en güçlü yanlarından biri, discoverable credentials desteğidir. Bu sayede kullanıcı, e-posta veya kullanıcı adı girmeden doğrudan cihazındaki passkey ile giriş yapabilir. authenticatorSelection.residentKey = "required" ve userVerification = "required" ayarlarıyla modern bir “tek dokunuşla giriş” deneyimi sağlayabilirsiniz.

Güvenlik ve Uyum İpuçları

- Her istek için tek kullanımlık random challenge üretin ve kısa süreliğine geçerli kılın.
- RP ID ve origin eşleşmesini sıkı tutun; üretim ve test ortamlarını karıştırmayın.
- Rate limiting ve risk tabanlı kontroller (IP, cihaz parmak izi, olağandışı saat dilimi) ekleyin.
- Kullanıcının passkey kaybına karşı yedek faktör (TOTP, e-posta onayı, güvenlik anahtarı) sunun; ancak bu faktörleri de phishing’e dayanıklı hale getirmeyi hedefleyin.
- Veritabanınızda publicKey, credentialId, signCount, transports, aaguid gibi alanları saklayın; ileride politika kararları için faydalıdır.

Test, Hata Ayıklama ve Ölçüm

Geliştirme sırasında tarayıcının geliştirici araçlarındaki WebAuthn panelini kullanın; sanal güvenlik anahtarlarıyla senaryoları çoğaltabilirsiniz. Kayıt ve giriş akışlarında challenge ömrü, origin eşleşmesi ve base64url dönüşümleri en sık hata yapılan noktalardır. Üretimde ise başarısızlık oranı, adım terk ve cihaz/OS dağılımı gibi metrikleri izleyip sürtünme noktalarını azaltın.

Sonuç: Daha Güvenli ve Daha Hızlı Giriş

Passkey, hem güvenliği hem de kullanıcı deneyimini aynı anda iyileştiren nadir teknolojilerden biri. Parola sıfırlama süreçleri, bot saldırıları ve sahte giriş sayfalarıyla uğraşmak yerine, kökünden daha sağlam bir mimariye geçiyorsunuz. Küçük bir pilot kuvvetle başlayıp kullanıcı kitlenizin cihaz dağılımını ölçün; ardından parolasız girişe kademeli geçiş stratejisi belirleyin. Doğru uygulandığında, yardım masası yükü azalır, giriş süreleri kısalır ve dönüşüm oranları gözle görülür biçimde artar.

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.

1 Kasım 2025 Cumartesi

Passkey (WebAuthn) ile Parolasız Giriş Nasıl Eklenir? Next.js ve SimpleWebAuthn ile Adım Adım

Passkey nedir ve neden şimdi?

Parolalar artık güvenliğin en zayıf halkası. Passkey, FIDO2 ve WebAuthn standartları ile çalışan, kimlik doğrulamayı cihazınızdaki güvenli donanım modüllerine (Secure Enclave, TPM) emanet eden parolasız bir giriş yöntemidir. Kimlik avına dayanıklıdır, şifre sızmalarından etkilenmez ve iCloud Anahtar Zinciri, Google Parola Yöneticisi ve Microsoft hesabı ile senkronize olabilir. Bu yazıda, modern bir React çerçevesi olan Next.js üzerinde SimpleWebAuthn kullanarak passkey entegrasyonunu adım adım kuracağız.

Mimariyi hızlıca anlayalım

WebAuthn iki temel akıştan oluşur: Kayıt (Registration) ve Giriş (Authentication). Sunucu “relying party” olarak bir challenge üretir, tarayıcı ve cihazınızdaki kimlik doğrulama modülü bu challenge’ı özel anahtar ile imzalar, sunucu da daha önce kaydedilen genel anahtar ile imzayı doğrular. Kritik parametreler: rpId (alan adınız), origin (https kökeniniz), user.id (kalıcı benzersiz kimlik), counter (replay saldırılarına karşı sayaç) ve userVerification (biyometrik/PIN doğrulaması). Hepsi doğru ayarlanmadığında tarayıcı güvenlik nedeniyle işlemi reddeder.

Gerekenler ve kurulum

Başlamak için Node.js 18+ ve Next.js 13+ önerilir. Örneklerde App Router kullanılacaktır. Projeyi oluşturmak için: npx create-next-app@latest passkey-demo. Ardından gerekli kütüphaneler: npm i @simplewebauthn/server @simplewebauthn/browser cookie. Basitlik için oturumları cookie ile yöneteceğiz; gerçek projede JWT veya session store tercih edebilirsiniz.

Kayıt (registration) akışı

1) Sunucu tarafı seçenek üretimi: Kullanıcı yeni bir passkey oluşturmak istediğinde generateRegistrationOptions ile istemciye seçenek döndürün. Örnek ayarlar: rpName: 'Örnek Uygulama', rpID: 'alanadiniz.com', userID: 'kalici-uuid', userName: '[email protected]', attestationType: 'none', authenticatorSelection: { residentKey: 'preferred', userVerification: 'preferred' }. Bu adımda kullanıcıya bir challenge ve uyumlu parametreler verilir.

2) İstemci tarafı oluşturma: Tarayıcıda startRegistration(options) çağrılır ve kullanıcı cihazındaki biyometrik/PIN doğrulaması tetiklenir. İşlem başarılıysa dönen attestationResponse’ı backend’e gönderirsiniz.

3) Doğrulama ve kaydetme: Sunucuda verifyRegistrationResponse ile origin ve rpID doğrulanır. Başarılıysa veritabanına şu alanları kaydedin: credentialId (Base64URL), publicKey, counter, userId, transports, tercihen aaguid ve device type. Bu kayıt, o kullanıcının passkey’inin “kamu anahtarını” temsil eder.

Giriş (authentication) akışı

1) Seçenek üretimi: generateAuthenticationOptions ile istemciye yeni bir challenge gönderin. Eğer sadece belirli kayıtlı kimlik bilgilerine izin vermek isterseniz allowCredentials içinde credentialId’leri gönderin. Parolasız deneyim için discoverable credentials (residentKey) tercih edilir.

2) İstemci doğrulaması: Tarayıcıda startAuthentication(options) çağrılır. Kullanıcı biyometrik/PIN ile onaylar, ortaya çıkan assertionResponse sunucuya gönderilir.

3) Sunucu doğrulaması: verifyAuthenticationResponse ile imza doğrulanır; challenge, origin, rpId ve counter kontrol edilir. Sayaç değeri yükseldiyse veritabanındaki counter güncellenir. Başarılıysa kullanıcıyı oturum açmış sayıp güvenli bir Set-Cookie ile session başlatın.

Üretim için kritik güvenlik ayarları

- HTTPS zorunludur. WebAuthn yalnızca güvenli kökenlerde çalışır (localhost hariç). Cloudflare, Vercel veya kendi Nginx ters proxy’nizle TLS sağlayın.

- rpID tam alan adınız olmalı ve origin ile uyumlu olmalı. Örn. app.ornek.com kullanıyorsanız http:// değil https://app.ornek.com üzerinden test edin.

- userVerification’ı en az preferred, kritik işlemlerde required yapın; böylece biyometri/PIN doğrulaması zorunlu olur.

- Attestation çoğu senaryoda none kalabilir. Cihaz sınıfı kontrolü istiyorsanız indirect veya direct kullanabilir, gizlilik etkilerini değerlendirmelisiniz.

- Orta katmanda rate limiting, CSRF koruması ve replay önlemleri (tek kullanımlık challenge, kısa süreli TTL) uygulayın.

Tarayıcı ve cihaz uyumluluğu

Güncel Chrome, Safari ve Edge sürümleri passkey’i destekliyor. iOS ve Android cihazlarda platform authenticator ile sorunsuz çalışır. Masaüstünde “telefonla doğrula” akışı (QR/BT) mümkün. Kullanıcılara “fiziksel güvenlik anahtarı” (YubiKey) ile ek kayıt yaptırmak da kurtarma planı olarak önerilir.

Sık karşılaşılan hatalar

NotAllowedError: Kullanıcı etkileşimi (click) yoksa veya işlem zaman aşımına uğradıysa görülür. İşlemleri buton tıklamasıyla başlatın ve timeout değerini 60–120 sn yapın.

InvalidStateError: Aynı cihazda aynı kullanıcı için tekrar kayıt deneniyorsa oluşabilir. Kayıt öncesi kullanıcıya mevcut passkey’i kaldırma veya yeni cihaz olarak ekleme seçenekleri sunun.

RP ID hatası: “The RP ID is not a registrable domain” mesajı alıyorsanız muhtemelen localhost dışı http kullanıyorsunuzdur. Her zaman https kullanın ve alan adınızın kökeni ile rpID’yi eşleştirin.

Sonuç ve öneriler

Passkey entegrasyonu hem güvenliği hem de dönüşümü artırır: kullanıcılar parolaları hatırlamak zorunda kalmaz, giriş süresi kısalır. Next.js ve SimpleWebAuthn ikilisiyle temel kurulum birkaç saat içinde tamamlanabilir. Üretimde çoklu cihaz desteği, kurtarma seçenekleri (ikinci passkey, e-posta destekli destek süreci), denetim kayıtları ve ayrıntılı telemetriyi (başarı/başarısızlık oranları, tarayıcı/cihaz dağılımı) planlayın. Parolasız geleceğe adım atmak için bugün küçük bir pilotla başlayabilir, kullanıcılarınızdan gelen geri bildirimlere göre akışı iyileştirebilirsiniz.

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.

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.

9 Ekim 2025 Perşembe

Passkey (FIDO2/WebAuthn) ile Parolasız Giriş: Modern Web Uygulamalarına Adım Adım Entegrasyon

Passkey ve WebAuthn Nedir, Neden Önemli?

Parolasız kimlik doğrulama, güvenlik ve kullanıcı deneyimi açısından modern webin en kritik dönüşümlerinden biri. Passkey teknolojisi, FIDO2 ve WebAuthn standartlarına dayanarak şifreleri tamamen ortadan kaldırır ve herkese açık anahtar kriptografisiyle phishing saldırılarını kökten azaltır. Kullanıcılar, platformlarının (iOS, Android, Windows, macOS) yerleşik güvenlik donanımını veya güvenlik anahtarlarını (YubiKey gibi) kullanarak tek dokunuşla giriş yapar. Bu makalede, bir web uygulamasına passkey (WebAuthn) entegrasyonunu adım adım, pratik ipuçlarıyla anlatıyorum.

WebAuthn Nasıl Çalışır? (Kısa Teknik Özet)

WebAuthn, tarayıcı üzerinden navigator.credentials API’si ile çalışır. Kayıt (registration) aşamasında sunucu bir challenge üretir ve tarayıcıya gönderir. Kullanıcının cihazı benzersiz bir anahtar çifti (özel/public) oluşturur; public key sunucuya kaydedilir. Giriş (authentication) aşamasında sunucu yine bir challenge yollar; cihaz, özel anahtarla bu challenge’ı imzalar ve tarayıcı imzayı sunucuya iletir. Sunucu public key ile imzayı doğruladığında kullanıcı giriş yapar. Şifre yoktur; dolayısıyla credential stuffing ve klasik phishing riskleri dramatik biçimde azalır.

Ön Koşullar ve Mimarinin Temelleri

Entegrasyon için HTTPS zorunludur; rpId (Relying Party ID) genellikle alan adınızın eTLD+1 biçimidir (örneğin example.com). Backend tarafında kayıt ve giriş için iki uç nokta gerekir: /webauthn/register ve /webauthn/login (veya benzer adlar). Bu uç noktalar challenge üretir, tarayıcıdan dönen yanıtları doğrular ve kimlik bilgilerini (credentialId, publicKey, aaguid vb.) saklar. Sunucu tarafında dilinize göre bir WebAuthn/FIDO2 kütüphanesi kullanmanız önerilir; örneğin Node.js için SimpleWebAuthn, .NET için Fido2NetLib, Go için popüler WebAuthn paketleri mevcuttur.

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

1) Sunucu, kullanıcı hesabı oluşturulurken bir kayıt challenge’ı üretir ve tarayıcıya dönüş yapar. Dönen JSON içinde publicKey alanı olmalıdır (rp, user, challenge, pubKeyCredParams gibi).

2) Tarayıcı tarafında kayıt isteği şu şekilde tetiklenir: const cred = await navigator.credentials.create({ publicKey: options });. Buradaki options, sunucunun verdiği PublicKeyCredentialCreationOptions içeriğidir.

3) Dönen credential, id, rawId, response.attestationObject ve response.clientDataJSON içerir. Bu verileri JSON’a uygun biçimde base64url kodlayıp sunucuya gönderin: POST /webauthn/register/verify.

4) Sunucu, attestation politikasına (genellikle attestation: "none") göre doğrulama yapar, public key ve credentialId’yi kullanıcıyla eşleştirip veritabanına kaydeder. COSE algoritması olarak ES256 varsayılan ve yaygın bir tercihtir.

Adım 2: Giriş (Authentication) ve Passkey Deneyimi

1) Giriş aşamasında sunucu bir doğrulama challenge’ı üretir ve tarayıcıya yollar. Eğer discoverable credentials (kullanıcı adı girmeden hesap seçimi yapılabilen passkey’ler) destekliyorsanız, allowCredentials alanını boş bırakabilirsiniz.

2) Tarayıcı, aşağıdaki çağrıyla kullanıcıdan biyometrik/doğrulama isteği alır: const assertion = await navigator.credentials.get({ publicKey: requestOptions });. Modern tarayıcı ve platformlarda, mediation: "conditional" ile otomatik doldurma benzeri akış sağlayabilirsiniz: navigator.credentials.get({ publicKey: requestOptions, mediation: "conditional" }).

3) Dönen yanıtta response.authenticatorData, response.clientDataJSON ve response.signature bulunur. Bu verileri sunucuya gönderin: POST /webauthn/login/verify. Sunucu, ilgili public key ile imzayı doğrular, signCount değerini günceller ve oturumu başlatır.

En İyi Uygulamalar ve UX İpuçları

Passkey deneyimi, kullanıcı adı ve şifre kutularını tamamen devre dışı bırakabilir. Özellikle Conditional UI desteği ile (Chrome, Android, iOS ve Safari’nin güncel sürümleri) sayfa yüklenir yüklenmez platform, uygun passkey’leri önerir. Kullanıcı tek dokunuşla giriş yapar. Formlarınızda “Passkey ile giriş yap” butonunu net biçimde gösterin; ilk kurulumda parolayı da kabul edip passkey oluşturma adımını teşvik ederek geçişi yumuşatın.

Hesap kurtarma için e-posta doğrulama, yedek güvenlik anahtarları veya müşteri destek süreçleri tasarlayın. Passkey’ler iCloud veya Google hesabı üzerinden cihazlar arasında senkronize olabilir; bu özellik, kullanıcı değişen cihazlarda bile sorunsuz giriş deneyimi sağlar.

Güvenlik ve Uyum Detayları

- HTTPS zorunludur; localhost geliştirme ortamında tarayıcılar özel izinler sunar. Üretimde mutlaka geçerli bir TLS sertifikası kullanın ve TLS 1.2+ desteğini aktif tutun.

- rpId, cookie SameSite ve Secure bayrakları, Origin eşleşmeleri gibi detaylar önemlidir. Ters proxy (Nginx/Caddy/Cloudflare) arkasında header’ların doğru yönlendirildiğinden emin olun.

- Attestation politikanızı iş gereksinimlerine göre belirleyin. Çoğu SaaS için none yeterlidir; regülasyonlu sektörlerde direct veya enterprise gerekebilir.

- Zaman senkronizasyonu (NTP) ve sunucu saat farkı doğrulamada rol oynar; bu nedenle saat kaymasını minimal tutun.

Test, Hata Ayıklama ve Yayına Alma

Geliştirme sırasında tarayıcı konsolunda Security ve Network sekmelerini izleyin; WebAuthn hataları genellikle açıklayıcıdır. localhost üzerinde test ederken rpId olarak “localhost” kullanın. İlk yayında, kademeli açılış (feature flag) ile kullanıcıların küçük bir yüzdesine passkey’i sunup metrikleri takip etmek iyi bir stratejidir: başarı oranı, iptal oranı, geri dönüşler ve destek talepleri ölçülmelidir.

Sonuç: Parolasız Geleceğe Bugünden Geçin

Passkey (FIDO2/WebAuthn) entegrasyonu; daha güvenli, daha hızlı ve daha kullanıcı dostu bir oturum açma deneyimi sağlar. Şifre sıfırlama maliyetlerini düşürür, hesap ele geçirme vakalarını azaltır ve mobil cihazlarda tek dokunuşla giriş imkânı sunar. Bu rehberdeki adımları izleyerek, önce hibrit (parola + passkey) modeliyle başlayabilir, ardından kullanıcılarınız hazır olduğunda tamamen parolasız bir geleceğe geçebilirsiniz.