Genel Bakış
Geçiş anahtarı kimlik doğrulamasında kullanılan temel adımlara dair genel bilgileri aşağıda bulabilirsiniz:
- 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.
- 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:
- 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.
- 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ındapublicKeyCredentialCreationOptions
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ı vechallenge
ü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 birNotAllowedError
atılır.
publicKeyCredentialRequestOptions
öğesini oluşturduktan sonra müşteriye gönderin.
Ö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.
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.authenticatorData
veresponse.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:
- 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
nesnesinderesponse.userHandle
öğesini kullanma. Kullanıcılar tablosunda,userHandle
ile eşleşenpasskey_user_id
'yi bulun. - 2. Seçenek:
PublicKeyCredential
nesnesinde bulunanid
kimlik bilgisini kullanın. Ortak anahtar kimlik bilgileri tablosunda,PublicKeyCredential
nesnesinde bulunanid
kimlik bilgisi ile eşleşenid
kimlik bilgisini bulun. Ardından, Kullanıcılar tablonuzdapasskey_user_id
yabancı anahtarını kullanarak ilgili kullanıcıyı arayın.
- 1. Seçenek:
- 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 bulunanid
kimlik bilgisi ile eşleşenid
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
öğesindekiuv
(kullanıcı tarafından doğrulanmış) işaretinintrue
olduğundan emin olun. Geçiş anahtarları için kullanıcı varlığı her zaman gerekli olduğundanauthenticatorData
ürünündekiup
(kullanıcı mevcut) işaretinintrue
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ı.
- İmza (imzalanmış sorgulama):
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.