Şifresiz girişler için geçiş anahtarı oluşturma

Geçiş anahtarları, kullanıcı hesaplarını daha güvenli, daha basit ve daha kolay hale getirir.

Geçiş anahtarları kullanmak güvenliği artırır, girişleri basitleştirir ve şifreleri değiştirir. Kullanıcıların hatırlaması ve manuel olarak girmesi gereken normal şifrelerin aksine geçiş anahtarları, cihazın biyometri veya PIN gibi ekran kilidi mekanizmalarını kullanır ve kimlik avı risklerini ve kimlik bilgisi hırsızlığını azaltır.

Geçiş anahtarları, Google Şifre Yöneticisi ve iCloud Anahtar Zinciri gibi geçiş anahtarı sağlayıcılar kullanılarak cihazlar arasında senkronize edilir.

Özel anahtar, gerekli meta verilerle birlikte geçiş anahtarı sağlayıcısında güvenli bir şekilde depolanan bir geçiş anahtarı oluşturulmalıdır. Geçiş anahtarının ortak anahtarı ise kimlik doğrulaması için sunucunuzda depolanır. Özel anahtar, geçerli alanda kullanıcı doğrulamasından sonra bir imza yayınlar. Bu sayede şifre anahtarları kimlik avına karşı dirençli hale gelir. Ortak anahtar, hassas kimlik bilgilerini depolamaksızın imzası doğrular. Bu sayede geçiş anahtarları, kimlik bilgisi hırsızlığına karşı dirençli hale gelir.

Geçiş anahtarı oluşturma işleminin işleyiş şekli

Kullanıcıların geçiş anahtarıyla oturum açabilmesi için geçiş anahtarını oluşturmanız, bir kullanıcı hesabıyla ilişkilendirmeniz ve herkese açık anahtarını sunucunuzda saklamanız gerekir.

Kullanıcılardan aşağıdaki durumlardan birinde geçiş anahtarı oluşturmalarını isteyebilirsiniz:

  • Kayıt sırasında veya sonrasında.
  • Oturum açtıktan sonra.
  • Başka bir cihazdaki geçiş anahtarını kullanarak oturum açtıktan sonra (yani [authenticatorAttachment](https://web.dev/articles/passkey-form-autofill#authenticator-attachment), cross-platform değerini alır).
  • Kullanıcıların şifre anahtarlarını yönetebileceği özel bir sayfada.

Geçiş anahtarı oluşturmak için WebAuthn API'yi kullanırsınız.

Geçiş anahtarı kayıt akışının dört bileşeni şunlardır:

  • Arka uç: Herkese açık anahtar dahil olmak üzere kullanıcı hesabı ayrıntılarını depolar.
  • Ön uç: Tarayıcı ile iletişim kurar ve arka uçtan gerekli verileri getirir.
  • Tarayıcı: JavaScript'inizi çalıştırır ve WebAuthn API ile etkileşim kurar.
  • Geçiş anahtarı sağlayıcı: Geçiş anahtarını oluşturur ve saklar. Bu genellikle Google Şifre Yöneticisi gibi bir şifre yöneticisi veya güvenlik anahtarıdır.
Geçiş anahtarı oluşturma ve kaydetme işlemi
Geçiş anahtarı oluşturma ve kaydetme işlemi.

Geçiş anahtarı oluşturmadan önce sistemin aşağıdaki ön koşulları karşıladığından emin olun:

  • Kullanıcı hesabı, kısa bir süre içinde güvenli bir yöntemle (ör. e-posta, telefon doğrulaması veya kimlik federasyonu) doğrulanır.

  • Ön uç ve arka uç, kimlik bilgisi verilerini paylaşmak için güvenli bir şekilde iletişim kurabilir.

  • Tarayıcı, WebAuthn'u ve geçiş anahtarı oluşturmayı desteklemelidir.

Bunların çoğunu nasıl kontrol edeceğinizi aşağıdaki bölümlerde gösterebiliriz.

Sistem bu koşulları karşıladıktan sonra geçiş anahtarı oluşturmak için aşağıdaki işlem gerçekleşir:

  1. Sistem, kullanıcı işlemi başlattığında (ör. geçiş anahtarı yönetim sayfasında "Geçiş anahtarı oluştur" düğmesini tıklayarak veya kaydını tamamladıktan sonra) geçiş anahtarı oluşturma işlemini tetikler.
  2. Kullanıcı arayüzü, yinelemeleri önlemek için kullanıcı bilgileri, bir istem ve kimlik bilgisi kimlikleri de dahil olmak üzere arka uçtan gerekli kimlik bilgisi verilerini ister.
  3. Kullanıcı arayüzü, cihazın geçiş anahtarı sağlayıcısından arka uçtaki bilgileri kullanarak geçiş anahtarı oluşturmasını istemek için navigator.credentials.create() işlevini çağırır. Bu çağrının bir promise döndürdüğünü unutmayın.
  4. Kullanıcının cihazı, geçiş anahtarını oluşturmak için biyometrik yöntem, PIN veya desen kullanarak kullanıcının kimliğini doğrular.
  5. Geçiş anahtarı sağlayıcısı bir geçiş anahtarı oluşturur ve kullanıcı arayüzüne bir ortak anahtar kimlik bilgisi döndürerek söz vermeyi çözer.
  6. Ön uç, oluşturulan ortak anahtar kimlik bilgisini arka uca gönderir.
  7. Arka uç, gelecekte kimlik doğrulama için ortak anahtarı ve diğer önemli verileri depolar.
  8. Arka uç, geçiş anahtarının oluşturulmasını onaylamak ve olası yetkisiz erişimi tespit etmek için kullanıcıyı (ör. e-posta kullanarak) bilgilendirir.

Bu işlem, kullanıcılar için güvenli ve sorunsuz bir geçiş anahtarı kayıt süreci sağlar.

Uyumluluk

Çoğu tarayıcı, bazı küçük boşluklar olsa da WebAuthn'u destekler. Tarayıcı ve işletim sistemi uyumluluğu ayrıntıları için passkeys.dev adresine bakın.

Yeni geçiş anahtarı oluşturma

Yeni bir geçiş anahtarı oluşturmak için ön uçta uygulanması gereken işlemler şunlardır:

  1. Uyumluluğu kontrol edin.
  2. Arka uçtan bilgi getirme
  3. Geçiş anahtarı oluşturmak için WebAuth API'yi çağırın.
  4. Geri döndürülen ortak anahtarı arka uca gönderin.
  5. Kimlik bilgisini kaydedin.

Aşağıdaki bölümlerde bunu nasıl yapabileceğiniz gösterilmektedir.

Uyumluluğu kontrol etme

"Yeni geçiş anahtarı oluştur" düğmesini göstermeden önce ön uç şunu kontrol etmelidir:

  • Tarayıcı, PublicKeyCredential ile WebAuthn'u desteklemelidir.

Browser Support

  • Chrome: 67.
  • Edge: 18.
  • Firefox: 60.
  • Safari: 13.

Source

  • Cihaz, PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable() ile platform kimlik doğrulayıcıyı destekler (geçiş anahtarı oluşturabilir ve geçiş anahtarıyla kimlik doğrulayabilir).

Browser Support

  • Chrome: 67.
  • Edge: 18.
  • Firefox: 60.
  • Safari: 13.

Source

Browser Support

  • Chrome: 108.
  • Edge: 108.
  • Firefox: 119.
  • Safari: 16.

Source

Aşağıdaki kod snippet'inde, geçiş anahtarıyla ilgili seçenekleri göstermeden önce uyumluluğu nasıl kontrol edebileceğiniz gösterilmektedir.

// Availability of `window.PublicKeyCredential` means WebAuthn is usable.  
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.  
// `isConditionalMediationAvailable` means the feature detection is usable.  
if (window.PublicKeyCredential &&  
    PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&  
    PublicKeyCredential.isConditionalMediationAvailable) {  
  // Check if user verifying platform authenticator is available.  
  Promise.all([  
    PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),  
    PublicKeyCredential.isConditionalMediationAvailable(),  
  ]).then(results => {  
    if (results.every(r => r === true)) {  
      // Display "Create a new passkey" button  
    }  
  });  
}  

Bu örnekte, Yeni geçiş anahtarı oluştur düğmesi yalnızca tüm koşullar karşılanırsa gösterilir.

Arka uçtan bilgi getirme

Kullanıcı düğmeyi tıkladığında, navigator.credentials.create()'ü aramak için arka uçtan gerekli bilgileri alın.

Aşağıdaki kod snippet'inde, navigator.credentials.create() çağrısı için gerekli bilgileri içeren bir JSON nesnesi gösterilmektedir:

// Example `PublicKeyCredentialCreationOptions` contents
{
  challenge: *****,
  rp: {
    name: "Example",
    id: "example.com",
  },
  user: {
    id: *****,
    name: "john78",
    displayName: "John",
  },
  pubKeyCredParams: [{
    alg: -7, type: "public-key"
  },{
    alg: -257, type: "public-key"
  }],
  excludeCredentials: [{
    id: *****,
    type: 'public-key',
    transports: ['internal'],
  }],
  authenticatorSelection: {
    authenticatorAttachment: "platform",
    requireResidentKey: true,
  }
}

Nesnedeki anahtar/değer çiftleri aşağıdaki bilgileri içerir:

  • challenge: Bu kayıt için sunucu tarafından oluşturulan ArrayBuffer'da bir istem.
  • rp.id: RP kimliği (Kullanıcı Tarafı Kimliği), alan adı ve web sitesi, alan adını veya kaydedilebilir bir son eki belirtebilir. Örneğin, bir RP'nin kaynağı https://login.example.com:1337 ise RP kimliği login.example.com veya example.com olabilir. RP kimliği example.com olarak belirtilirse kullanıcı login.example.com'da veya login.example.com'daki herhangi bir alt alan adında kimlik doğrulaması yapabilir.example.com Bu konuda daha fazla bilgi için İlgili Kaynak İstekleri ile sitelerinizde geçiş anahtarının yeniden kullanılmasına izin verme başlıklı makaleyi inceleyin.
  • rp.name: Kısıtlanmış tarafın (güvenilir tarafın) adı. Bu özelliğin desteği WebAuthn L3'te sonlandırılmıştır ancak uyumluluk nedeniyle dahil edilmiştir.
  • user.id: Hesap oluşturulduğunda oluşturulan, ArrayBuffer biçiminde benzersiz bir kullanıcı kimliği. Düzenlenebilir bir kullanıcı adının aksine kalıcı olmalıdır. Kullanıcı kimliği bir hesabı tanımlar ancak kimliği tanımlayabilecek bilgiler (PII) içermemelidir. Sisteminizde muhtemelen bir kullanıcı kimliğiniz vardır ancak gerekirse kimliği, kimlik bilgisi içermeyecek şekilde geçiş anahtarları için özel olarak oluşturun.
  • user.name: Hesap için kullanıcının tanıyacağı benzersiz bir tanımlayıcı (e-posta adresi veya kullanıcı adı gibi). Bu, hesap seçicide gösterilir.
  • user.displayName: Hesap için zorunlu olan, daha kullanıcı dostu bir ad. Benzersiz olması gerekmez ve kullanıcının seçtiği ad olabilir. Sitenizde buraya dahil edilecek uygun bir değer yoksa boş bir dize gönderin. Bu bilgi, tarayıcıya bağlı olarak hesap seçicide gösterilebilir.
  • pubKeyCredParams: RP (güvenilir taraf) tarafından desteklenen ortak anahtar algoritmalarını belirtir. [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}] olarak ayarlamanızı öneririz. Bu, P-256 ve RSA PKCS#1 ile ECDSA desteğini belirtir ve bunların desteklenmesi tam kapsam sağlar.
  • excludeCredentials: Zaten kayıtlı kimlik bilgisi kimliklerinin listesi. Zaten kayıtlı kimlik bilgisi kimliklerinin listesini sağlayarak aynı cihazın iki kez kaydedilmesini engeller. Sağlandıysa transports üyesi, her kimlik bilgisinin kaydı sırasında getTransports() çağrısının sonucunu içermelidir.
  • authenticatorSelection.authenticatorAttachment: Geçiş anahtarı oluşturma işlemi, oturum açtıktan sonra bir promosyonda şifreye kıyasla yükseltme işlemiyse bu değeri hint: ['client-device'] ile birlikte "platform" olarak ayarlayın. "platform", RP'nin örneğin USB güvenlik anahtarı takma istemi göstermeyen bir platform kimlik doğrulayıcı (platform cihazına yerleştirilmiş bir kimlik doğrulayıcı) istediğini gösterir. Kullanıcının geçiş anahtarı oluşturmak için daha basit bir seçeneği vardır.
  • authenticatorSelection.requireResidentKey: Boole true olarak ayarlayın. Keşfedilebilir kimlik bilgisi (yerleşik anahtar), kullanıcı bilgilerini geçiş anahtarında depolar ve kullanıcıların kimlik doğrulamasından sonra hesabı seçmesine olanak tanır.
  • authenticatorSelection.userVerification: Cihaz ekran kilidinin kullanıldığı kullanıcı doğrulamasının "required", "preferred" veya "discouraged" olup olmadığını belirtir. Varsayılan ayar "preferred"'tür. Bu, kimlik doğrulayıcının kullanıcı doğrulamasını atlayabileceği anlamına gelir. Bu değeri "preferred" olarak ayarlayın veya mülkü çıkarın.

Nesneyi sunucuda oluşturmanızı, ArrayBuffer'ı Base64URL ile kodlamanızı ve ön uçtan getirmenizi öneririz. Bu şekilde, PublicKeyCredential.parseCreationOptionsFromJSON() kullanarak yükü çözebilir ve doğrudan navigator.credentials.create()'a iletebilirsiniz.

Aşağıdaki kod snippet'inde, geçiş anahtarını oluşturmak için gereken bilgileri nasıl alıp kodlarını nasıl çözebileceğiniz gösterilmektedir.

// Fetch an encoded `PubicKeyCredentialCreationOptions` from the server.
const _options = await fetch('/webauthn/registerRequest');

// Deserialize and decode the `PublicKeyCredentialCreationOptions`.
const decoded_options = JSON.parse(_options);
const options = PublicKeyCredential.parseCreationOptionsFromJSON(decoded_options);
...

Geçiş anahtarı oluşturmak için WebAuthn API'yi çağırma

Yeni bir geçiş anahtarı oluşturmak için navigator.credentials.create() numaralı telefonu arayın. API, kullanıcının etkileşimini bekleyen bir modal iletişim kutusu görüntüleyerek bir söz döndürür.

Browser Support

  • Chrome: 60.
  • Edge: 18.
  • Firefox: 60.
  • Safari: 13.

Source

// Invoke WebAuthn to create a passkey.
const credential = await navigator.credentials.create({
  publicKey: options
});

Döndürülen ortak anahtar kimlik bilgisini arka uca gönderme

Kullanıcı, cihazın ekran kilidi kullanılarak doğrulandıktan sonra bir geçiş anahtarı oluşturulur ve söz, ön uçta bir PublicKeyCredential nesnesi döndürülerek çözülür.

Taahhüt farklı nedenlerle reddedilebilir. Error nesnesinin name özelliğini kontrol ederek bu hataları giderebilirsiniz:

  • InvalidStateError: Cihazda zaten bir geçiş anahtarı var. Kullanıcıya hata iletişim kutusu gösterilmez. Site bunu bir hata olarak değerlendirmemelidir. Kullanıcı, yerel cihazın kaydedilmesini istedi ve cihaz kaydedildi.
  • NotAllowedError: Kullanıcı işlemi iptal etti.
  • AbortError: İşlem iptal edildi.
  • Diğer istisnalar: Beklenmeyen bir hata oluştu. Tarayıcı, kullanıcıya bir hata iletişim kutusu gösterir.

Ortak anahtar kimlik bilgisi nesnesi aşağıdaki özellikleri içerir:

  • id: Oluşturulan geçiş anahtarının Base64URL olarak kodlanmış kimliği. Bu kimlik, kimlik doğrulama yapıldıktan sonra tarayıcının cihazda eşleşen bir geçiş anahtarı olup olmadığını belirlemesine yardımcı olur. Bu değer, arka uçtaki veritabanında depolanmalıdır.
  • rawId: Kimlik bilgisi kimliğinin ArrayBuffer sürümü.
  • response.clientDataJSON: ArrayBuffer olarak kodlanmış müşteri verileri.
  • response.attestationObject: ArrayBuffer kodlu bir doğrulama nesnesi. Bu, RP kimliği, işaretler ve genel anahtar gibi önemli bilgileri içerir.
  • authenticatorAttachment: Bu kimlik bilgisi geçiş anahtarı özellikli bir cihazda oluşturulduğunda "platform" döndürülür.
  • type: Bu alan her zaman "public-key" olarak ayarlanır.

Nesneyi .toJSON() yöntemiyle kodlayın, JSON.stringify() ile seri hale getirin ve ardından sunucuya gönderin.

...

// Encode and serialize the `PublicKeyCredential`.
const _result = credential.toJSON();
const result = JSON.stringify(_result);

// Encode and send the credential to the server for verification.  
const response = await fetch('/webauthn/registerResponse', {
  method: 'post',
  credentials: 'same-origin',
  body: result
});
...

Kimlik bilgisini kaydetme

Arka uçta ortak anahtar kimlik bilgisini aldıktan sonra, ortak anahtar kimlik bilgisini işlemek için kendi kodunuzu yazmak yerine sunucu tarafı bir kitaplık veya çözüm kullanmanızı öneririz.

Ardından, kimlik bilgisinden alınan bilgileri gelecekte kullanmak üzere veritabanında saklayabilirsiniz.

Aşağıdaki listede, kaydedilmesi önerilen özellikler yer almaktadır:

  • Kimlik bilgisi kimliği: Ortak anahtar kimlik bilgisiyle döndürülen kimlik bilgisi kimliği.
  • Kimlik bilgisi adı: Kimlik bilgisinin adı. AAGUID'ye göre tanımlanabilen, geçiş anahtarını oluşturan geçiş anahtarı sağlayıcının adıyla adlandırın.
  • Kullanıcı kimliği: Geçiş anahtarını oluşturmak için kullanılan kullanıcı kimliği.
  • Ortak anahtar: Ortak anahtar kimlik bilgisiyle döndürülen ortak anahtar. Bu, geçiş anahtarı beyanını doğrulamak için gereklidir.
  • Oluşturma tarihi ve saati: Geçiş anahtarının oluşturulduğu tarihi ve saati kaydedin. Bu, geçiş anahtarını tanımlamak için yararlıdır.
  • Son kullanım tarihi ve saati: Kullanıcının oturum açmak için geçiş anahtarını kullandığı son tarihi ve saati kaydeder. Bu, kullanıcının hangi geçiş anahtarını kullandığını (veya kullanmadığını) belirlemek için yararlıdır.
  • AAGUID: Geçiş anahtarı sağlayıcısının benzersiz tanımlayıcısıdır.
  • Yedekleme Uygunluğu işareti: Cihaz geçiş anahtarı senkronizasyonu için uygunsa doğru değerini alır. Bu bilgiler, kullanıcıların geçiş anahtarı yönetimi sayfasında senkronize edilebilir geçiş anahtarlarını ve cihaza bağlı (senkronize edilemez) geçiş anahtarlarını belirlemelerine yardımcı olur.

Sunucu tarafı geçiş anahtarı kaydı başlıklı makaledeki daha ayrıntılı talimatları uygulayın.

Kayıt başarısız olursa sinyal

Geçiş anahtarı kaydı başarısız olursa kullanıcının kafası karışabilir. Geçiş anahtarı sağlayıcısında geçiş anahtarı varsa ve bu anahtar kullanıcı tarafından kullanılabiliyorsa ancak ilişkili herkese açık anahtar sunucu tarafında depolanmamışsa geçiş anahtarını kullanarak yapılan oturum açma denemeleri hiçbir zaman başarılı olmaz ve bu sorunun giderilmesi zordur. Bu durumda kullanıcıya bilgi verdiğinizden emin olun.

Bu tür bir durumu önlemek için Signal API'yi kullanarak geçiş anahtarı sağlayıcıya bilinmeyen bir geçiş anahtarı sinyali gönderebilirsiniz. RP, PublicKeyCredential.signalUnknownCredential()'ü bir RP kimliği ve kimlik bilgisi kimliğiyle çağırarak geçiş anahtarı sağlayıcıyı, belirtilen kimlik bilgisinin kaldırıldığı veya mevcut olmadığı konusunda bilgilendirebilir. Bu sinyalle nasıl başa çıkılacağı geçiş anahtarı sağlayıcıya bağlıdır ancak destekleniyorsa ilişkili geçiş anahtarının kaldırılması beklenir.

// Detect authentication failure due to lack of the credential
if (response.status === 404) {
  // Feature detection
  if (PublicKeyCredential.signalUnknownCredential) {
    await PublicKeyCredential.signalUnknownCredential({
      rpId: "example.com",
      credentialId: "vI0qOggiE3OT01ZRWBYz5l4MEgU0c7PmAA" // base64url encoded credential ID
    });
  } else {
    // Encourage the user to delete the passkey from the password manager nevertheless.
    ...
  }
}

Signal API hakkında daha fazla bilgi edinmek için Signal API ile geçiş anahtarlarını sunucunuzdaki kimlik bilgileriyle tutarlı tutma başlıklı makaleyi inceleyin.

Kullanıcıya bildirim gönderme

Geçiş anahtarı kaydedildiğinde bildirim (e-posta gibi) gönderilmesi, kullanıcıların yetkisiz hesap erişimini tespit etmesine yardımcı olur. Bir saldırgan, kullanıcının bilgisi olmadan geçiş anahtarı oluşturursa geçiş anahtarı, şifre değiştirildikten sonra bile gelecekte kötüye kullanım için kullanılabilir. Bildirim, kullanıcıyı uyarır ve bu durumun önlenmesine yardımcı olur.

Yapılacaklar listesi

  • Geçiş anahtarı oluşturmasına izin vermeden önce kullanıcıyı doğrulayın (tercihen e-posta veya güvenli bir yöntem kullanarak).
  • excludeCredentials kullanarak aynı geçiş anahtarı sağlayıcısı için yinelenen geçiş anahtarlarının oluşturulmasını engelleyin.
  • Geçiş anahtarı sağlayıcıyı tanımlamak ve kullanıcının kimlik bilgisini adlandırmak için AAGUID'yi kaydedin.
  • Geçiş anahtarı kaydetme girişimi PublicKeyCredential.signalUnknownCredential() ile başarısız olursa sinyal gönderin.
  • Hesabı için geçiş anahtarı oluşturup kaydettikten sonra kullanıcıya bildirim gönderin.

Kaynaklar

Sonraki adım: Form otomatik doldurma özelliğiyle geçiş anahtarıyla oturum açma.