Sunucu tarafı geçiş anahtarı kimlik doğrulaması

Genel Bakış

Geçiş anahtarı kimlik doğrulamasında kullanılan temel adımlara dair genel bilgileri aşağıda bulabilirsiniz:

Geçiş anahtarı kimlik doğrulama akışı

  • Geçiş anahtarıyla kimlik doğrulamak için gereken sorgulamayı ve diğer seçenekleri tanımlayın. Bu anahtarları, geçiş anahtarı kimlik doğrulama aramanıza (web'de navigator.credentials.get) iletebilmeniz için istemciye gönderin. Kullanıcı geçiş anahtarı kimlik doğrulamasını onayladıktan sonra geçiş anahtarı kimlik doğrulama çağrısı çözümlenir ve bir kimlik bilgisi (PublicKeyCredential) döndürür. Kimlik bilgisi bir kimlik doğrulama onayı içeriyor.
ziyaret edin.
  • Kimlik doğrulama onayını doğrulayın.
  • Kimlik doğrulama onayı geçerliyse kullanıcının kimliğini doğrulayın.

Aşağıdaki bölümlerde her bir adımın ayrıntıları açıklanmaktadır.

Meydan okumayı oluştur

Pratikte görev, ArrayBuffer nesnesi olarak gösterilen rastgele baytlardan oluşan bir dizidir.

// Example challenge, base64URL-encoded
weMLPOSx1VfSnMV6uPwDKbjGdKRMaUDGxeDEUTT5VN8

Görevin amacına uygun olduğundan emin olmak için aşağıdakileri yapmanız gerekir:

  1. Aynı giriş sorgulamasının hiçbir zaman birden fazla kez kullanıldığından emin olun. Her oturum açma denemesinde yeni bir sorgulama oluşturma Başarılı veya başarısız olması fark etmeksizin her oturum açma denemesinden sonra sorgulamayı silin. Belirli bir süre sonra görevi de siler. Bir yanıtta aynı soruyu asla birden fazla kez kabul etmeyin.
  2. Sorgunun kriptografik olarak güvenli olduğundan emin olun. Bir görevin tahmin edilmesi neredeyse imkansız olmalıdır. Sunucu tarafında şifreleme açısından güvenli bir sorgulama oluşturmak için güvendiğiniz bir FIDO sunucu tarafı kitaplığını kullanmanız önerilir. Bunun yerine kendi meydan okumalarınızı oluşturuyorsanız teknoloji yığınınızda bulunan yerleşik şifreleme işlevini kullanın veya kriptografik kullanım alanları için tasarlanmış kitaplıkları arayın. Buna örnek olarak Node.js'deki iso-crypto veya Python'daki gizli anahtarlar verilebilir. Spesifikasyona göre, sorgulamanın güvenli kabul edilmesi için en az 16 bayt uzunluğunda olması gerekir.

Oluşturduğunuz bir sorgulamayı daha sonra doğrulamak için kullanıcının oturumuna kaydedin.

Kimlik bilgisi isteği seçenekleri oluşturma

publicKeyCredentialRequestOptions nesnesi olarak kimlik bilgisi isteği seçenekleri oluşturun.

Bunu yapmak için FIDO sunucu tarafı kitaplığınızı kullanın. Genellikle sizin için bu seçenekleri oluşturabilecek bir yardımcı program işlevi sunar. SimpleWebAuthn teklifleri, örneğin, generateAuthenticationOptions.

publicKeyCredentialRequestOptions, geçiş anahtarıyla kimlik doğrulama için gereken tüm bilgileri içermelidir. Bu bilgiyi, FIDO sunucu tarafı kitaplığınızda publicKeyCredentialRequestOptions nesnesini oluşturmaktan sorumlu işleve iletin.

Bazı publicKeyCredentialRequestOptions. alanları sabit olabilir. Diğerleri sunucuda dinamik olarak tanımlanmalıdır:

  • rpId: Kimlik bilgisinin ilişkilendirilmesini beklediğiniz Kısıtlanmış Taraf Kimliği (ör. example.com). Kimlik doğrulama yalnızca burada sağladığınız Kısıtlanmış Taraf Kimliği, kimlik bilgileriyle ilişkili Kısıtlanmış Taraf Kimliği ile eşleşirse başarılı olur. Kısıtlanmış taraf kimliğini doldurmak için kimlik bilgisi kaydı sırasında publicKeyCredentialCreationOptions içinde ayarladığınız Kısıtlanmış Taraf Kimliği ile aynı değeri kullanın.
  • challenge: Geçiş anahtarı sağlayıcısının, kimlik doğrulama isteği anında kullanıcının geçiş anahtarını elinde tuttuğunu kanıtlamak için imzalayacağı veri parçasıdır. Ayrıntıları, Görevi oluşturma bölümünde inceleyebilirsiniz.
  • allowCredentials: Bu kimlik doğrulama için kabul edilebilir kimlik bilgileri dizisi. Kullanıcının tarayıcı tarafından gösterilen listeden kullanılabilir bir geçiş anahtarı seçmesine izin vermek için boş bir dizi iletin. Ayrıntılar için Kısıtlanmış taraf sunucusundan bir görev getirme ve Keşfedilebilir kimlik bilgileri ayrıntılı incelemesi makalelerini inceleyin.
  • userVerification: Cihaz ekran kilidini kullanarak doğrulama işleminin "gerekli" mi, "tercih edilen" mi olduğunu belirtir. veya "önerilmez". Kısıtlanmış taraf sunucusundan bir görev getirme başlıklı makaleyi inceleyin.
  • timeout: Kullanıcının kimlik doğrulamayı tamamlaması için gereken süre (milisaniye cinsinden). Makul ölçüde cömert olmalı ve challenge ürününün kullanım ömründen kısa olmalıdır. Önerilen varsayılan değer 5 dakikadır ancak bu değeri 10 dakikaya kadar artırabilirsiniz. Bu süre, önerilen aralıkta kalmaya devam eder. Uzun zaman aşımları, kullanıcıların genellikle biraz daha uzun süren karma iş akışını kullanmasını bekliyorsanız mantıklıdır. İşlem zaman aşımına uğrarsa bir NotAllowedError atılır.

publicKeyCredentialRequestOptions öğesini oluşturduktan sonra müşteriye gönderin.

Sunucu tarafından gönderilen publicKeyCredentialCreationOptions
Sunucu tarafından gönderilen seçenekler. challenge kod çözme işlemi istemci tarafında gerçekleşir.

Örnek kod: kimlik bilgisi isteği seçenekleri oluşturma

Örneklerimizde SimpleWebAuthn kitaplığını kullanıyoruz. Burada, kimlik bilgisi isteği seçeneklerinin oluşturulmasını generateAuthenticationOptions işlevine aktarıyoruz.

import {
  generateRegistrationOptions,
  verifyRegistrationResponse,
  generateAuthenticationOptions,
  verifyAuthenticationResponse
} from '@simplewebauthn/server';

router.post('/signinRequest', csrfCheck, async (req, res) => {

  // Ensure you nest calls in try/catch blocks.
  // If something fails, throw an error with a descriptive error message.
  // Return that message with an appropriate error code to the client.
  try {
    // Use the generateAuthenticationOptions function from SimpleWebAuthn
    const options = await generateAuthenticationOptions({
      rpID: process.env.HOSTNAME,
      allowCredentials: [],
    });
    // Save the challenge in the user session
    req.session.challenge = options.challenge;

    return res.json(options);
  } catch (e) {
    console.error(e);
    return res.status(400).json({ error: e.message });
  }
});

Kullanıcıyı doğrulayın ve oturum açın

navigator.credentials.get, istemcide başarıyla çözümlendiğinde bir PublicKeyCredential nesnesi döndürür.

Sunucu tarafından gönderilen PublicKeyCredential nesnesi
navigator.credentials.get, PublicKeyCredential döndürür.

response bir AuthenticatorAssertionResponse. Geçiş anahtarı sağlayıcısının, istemcinin RP'de geçiş anahtarıyla kimlik doğrulaması yapmak için gerekenleri oluşturma talimatına verdiği yanıtı temsil eder. Şunları içerir:

  • response.authenticatorDataveresponse.clientDataJSON (geçiş anahtarı kaydı adımındaki gibi).
  • Bu değerlerin üzerinde bir imza içeren response.signature.

PublicKeyCredential nesnesini sunucuya gönderin.

Sunucuda aşağıdakileri yapın:

Veritabanı şeması
Önerilen veritabanı şeması. Bu tasarım hakkında daha fazla bilgi için Sunucu tarafı geçiş anahtarı kaydı bölümüne bakın.
  • Onayı doğrulamak ve kullanıcının kimliğini doğrulamak için ihtiyaç duyacağınız bilgileri toplayın:
    • Kimlik doğrulama seçeneklerini oluşturduğunuzda oturumda depoladığınız beklenen sorgulamayı alın.
    • Beklenen origin ve RP kimliğini alın.
    • Veritabanınızda kullanıcının kim olduğunu bulun. Bulunabilir kimlik bilgileri söz konusu olduğunda, kimlik doğrulama isteğinde bulunan kullanıcının kim olduğunu bilemezsiniz. Bunu öğrenmek için iki seçeneğiniz var:
      • 1. Seçenek: PublicKeyCredential nesnesinde response.userHandle öğesini kullanma. Kullanıcılar tablosunda, userHandle ile eşleşen passkey_user_id'yi bulun.
      • 2. Seçenek: PublicKeyCredential nesnesinde bulunan id kimlik bilgisini kullanın. Ortak anahtar kimlik bilgileri tablosunda, PublicKeyCredential nesnesinde bulunan id kimlik bilgisi ile eşleşen id kimlik bilgisini bulun. Ardından, Kullanıcılar tablonuzda passkey_user_id yabancı anahtarını kullanarak ilgili kullanıcıyı arayın.
    • Veritabanınızda, aldığınız kimlik doğrulama onayıyla eşleşen ortak anahtar kimlik bilgisi bilgilerini bulun. Bunu yapmak için Ortak anahtar kimlik bilgileri tablosunda, PublicKeyCredential nesnesinde bulunan idkimlik bilgisi ile eşleşen id kimlik bilgisini arayın.
  • Kimlik doğrulama onayını doğrulayın. Bu doğrulama adımını, genellikle bu amaca yönelik bir yardımcı program işlevi sunan FIDO sunucu tarafı kitaplığınıza verin. SimpleWebAuthn teklifleri, örneğin, verifyAuthenticationResponse. Ek: Kimlik doğrulama yanıtının doğrulanması bölümünden, arka planda gerçekleşen gelişmeler hakkında bilgi edinebilirsiniz.

  • Saldırıların tekrarlanmasını önlemek için doğrulamanın başarılı olup olmadığına bakılmaksızın görevi silin.

  • Kullanıcının oturumunu açın. Doğrulama başarılı olduysa kullanıcıyı oturum açmış olarak işaretlemek için oturum bilgilerini güncelleyin. Kullanıcı arabiriminin yeni oturum açan kullanıcıyla ilişkili bilgileri kullanabilmesi için istemciye bir user nesnesi döndürmek de isteyebilirsiniz.

Örnek kod: Kullanıcıyı doğrulayın ve oturum açın

Örneklerimizde SimpleWebAuthn kitaplığını kullanıyoruz. Burada, kimlik doğrulama yanıtının doğrulamasını verifyAuthenticationResponse işlevine devrederiz.

import {
  generateRegistrationOptions,
  verifyRegistrationResponse,
  generateAuthenticationOptions,
  verifyAuthenticationResponse
} from '@simplewebauthn/server';
import { isoBase64URL } from '@simplewebauthn/server/helpers';

router.post('/signinResponse', csrfCheck, async (req, res) => {
  const response = req.body;
  const expectedChallenge = req.session.challenge;
  const expectedOrigin = getOrigin(req.get('User-Agent'));
  const expectedRPID = process.env.HOSTNAME;

  // Ensure you nest verification function calls in try/catch blocks.
  // If something fails, throw an error with a descriptive error message.
  // Return that message with an appropriate error code to the client.
  try {
    // Find the credential stored to the database by the credential ID
    const cred = Credentials.findById(response.id);
    if (!cred) {
      throw new Error('Credential not found.');
    }
    // Find the user - Here alternatively we could look up the user directly
    // in the Users table via userHandle
    const user = Users.findByPasskeyUserId(cred.passkey_user_id);
    if (!user) {
      throw new Error('User not found.');
    }
    // Base64URL decode some values
    const authenticator = {
      credentialPublicKey: isoBase64URL.toBuffer(cred.publicKey),
      credentialID: isoBase64URL.toBuffer(cred.id),
      transports: cred.transports,
    };

    // Verify the credential
    const { verified, authenticationInfo } = await verifyAuthenticationResponse({
      response,
      expectedChallenge,
      expectedOrigin,
      expectedRPID,
      authenticator,
      requireUserVerification: false,
    });

    if (!verified) {
      throw new Error('User verification failed.');
    }

    // Kill the challenge for this session.
    delete req.session.challenge;

    req.session.username = user.username;
    req.session['signed-in'] = 'yes';

    return res.json(user);
  } catch (e) {
    delete req.session.challenge;

    console.error(e);
    return res.status(400).json({ error: e.message });
  }
});

Ek: kimlik doğrulama yanıtının doğrulanması

Kimlik doğrulama yanıtının doğrulanması aşağıdaki kontrollerden oluşur:

  • Kısıtlanmış taraf kimliğinin sitenizle eşleştiğinden emin olun.
  • İsteğin kaynağının sitenizin oturum açma kaynağıyla eşleştiğinden emin olun. Android uygulamaları için Kaynağı doğrulama başlıklı makaleyi inceleyin.
  • Cihazın, isteği yerine getirip getirmediğini kontrol edin.
  • Kimlik doğrulama sırasında kullanıcının, kısıtlanmış taraf olarak zorunlu kıldığı koşulları karşıladığını doğrulayın. Kullanıcı doğrulamasına ihtiyaç duyuyorsanız authenticatorData öğesindeki uv (kullanıcı tarafından doğrulanmış) işaretinin true olduğundan emin olun. Geçiş anahtarları için kullanıcı varlığı her zaman gerekli olduğundan authenticatorData ürünündeki up (kullanıcı mevcut) işaretinin true olduğundan emin olun.
  • İmzayı doğrulayın. İmzayı doğrulamak için gerekenler:
    • İmza (imzalanmış sorgulama): response.signature
    • İmzanın doğrulanması için kullanılacak ortak anahtar.
    • Orijinal olarak imzalanmış veriler. Bu veriler, imzası doğrulanacak verilerdir.
    • İmza oluşturmak için kullanılan şifreleme algoritması.
ziyaret edin.

Bu adımlar hakkında daha fazla bilgi edinmek için SimpleWebAuthn'un verifyAuthenticationResponse kaynak koduna göz atın veya spesifikasyonda doğrulamaların tam listesini inceleyin.