Genel bakış
Geçiş anahtarı kimlik doğrulamasıyla ilgili temel adımlara genel bakışı burada bulabilirsiniz:
- Geçiş anahtarı ile kimlik doğrulamak için gereken sorgulamayı ve diğer seçenekleri tanımlayın. Bunları, 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çerir.
- 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 adımın ayrıntıları açıklanmaktadır.
Meydan okumayı oluşturun
Pratikte sorgulama, ArrayBuffer
nesnesi olarak temsil edilen bir rastgele bayt dizisidir.
// Example challenge, base64URL-encoded
weMLPOSx1VfSnMV6uPwDKbjGdKRMaUDGxeDEUTT5VN8
Yarışmanın amacına ulaşmasını sağlamak için şunları yapmalısınız:
- Aynı giriş sorgulamasının hiçbir zaman bir defadan fazla kullanılmadığından emin olun. Her oturum açma denemesinde yeni bir giriş sorgulaması oluştur. Başarılı veya başarısız olsa da her oturum açma denemesinden sonra sorgulamayı silin. Ayrıca, belirli bir süre sonra meydan okumayı sil. Bir yanıtta aynı sorgulamayı hiçbir zaman bir defadan fazla kabul etmeyin.
- Sorgunun kriptografik olarak güvenli olduğundan emin olun. Bir zorluğun tahmin edilmesi neredeyse imkansız olmalıdır. Sunucu tarafında kriptografik olarak güvenli bir giriş sorgulaması oluşturmak için güvendiğiniz bir FIDO sunucu tarafı kitaplığını kullanmanız en iyisidir. Bunun yerine kendi girişlerinizi oluşturursanı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. Node.js'de iso-crypto veya Python'daki secrets örnek olarak verilebilir. Spesifikasyona göre, sorgulamanın güvenli olarak kabul edilmesi için en az 16 bayt uzunluğunda olması gerekir.
Bir egzersiz oluşturduktan sonra, daha sonra doğrulamak için bu testi kullanıcının oturumuna kaydedin.
Kimlik bilgisi isteği seçeneklerini 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. Bu özellik 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ı kimlik doğrulaması için gereken tüm bilgileri içermelidir. Bu bilgileri, FIDO sunucu tarafı kitaplığınızda bulunan publicKeyCredentialRequestOptions
nesnesini oluşturmaktan sorumlu olan işleve iletin.
publicKeyCredentialRequestOptions
'lik alanların bazıları sabit değer 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 RP Kimliği, kimlik bilgisiyle ilişkilendirilen RP Kimliği ile eşleşirse başarılı olur. RP kimliğini doldurmak için kimlik bilgisi kaydı sırasındapublicKeyCredentialCreationOptions
alanında belirlediğiniz RP Kimliği ile aynı değeri kullanın.challenge
: Kimlik doğrulama isteği yapılırken kullanıcının şifre anahtarını elinde bulundurduğunu kanıtlamak için geçiş anahtarı sağlayıcısının imzalayacağı veri parçasıdır. Ayrıntıları Yarışma oluşturma başlıklı makalede inceleyebilirsiniz.allowCredentials
: Bu kimlik doğrulama için kabul edilebilir kimlik bilgileri dizisidir. 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ılı bilgi için Get a egzersiz from the RP server (RP sunucusundan bir giriş sorgulaması alma) ve Keşfedilebilir kimlik bilgilerinin ayrıntılı incelemesi sayfalarını inceleyin.userVerification
: Cihaz ekran kilidi kullanılarak yapılan kullanıcı doğrulamasının "gerekli", "tercih edilen" veya "önerilmez" olup olmadığını belirtir. RP sunucusundan bir giriş sorgulaması getir konusunu inceleyin.timeout
: Kullanıcının kimlik doğrulamayı tamamlama süresi (milisaniye cinsinden). Makul düzeyde cömert olmalı vechallenge
kullanım ömründen daha kısa sürmelidir. Önerilen varsayılan değer 5 dakika'dır ancak bu değeri 10 dakikaya kadar artırabilirsiniz. Bu değer hâlâ önerilen aralık dahilindedir. Kullanıcıların, genellikle biraz daha uzun süren karma iş akışını kullanmasını bekliyorsanız uzun zaman aşımları mantıklıdır. İşlem zaman aşımına uğrarsa birNotAllowedError
atılır.
publicKeyCredentialRequestOptions
dosyasını 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çeneklerini oluşturma işlemini 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 PublicKeyCredential
nesnesi döndürür.
response
bir AuthenticatorAssertionResponse
. Geçiş anahtarı sağlayıcısının, istemcinin RP'deki geçiş anahtarıyla kimlik doğrulamayı denemek için gereken işlemi oluşturma talimatına verdiği yanıtı temsil eder. Şunları içerir:
response.authenticatorData
veresponse.clientDataJSON
(ör. geçiş anahtarı kaydı adımında olduğu gibi).- Bu değerlerin üzerinde bir imza içeren
response.signature
.
PublicKeyCredential
nesnesini sunucuya gönderin.
Sunucuda aşağıdakileri yapın:
- Onayı ve kullanıcının kimliğini doğrulamak için ihtiyacınız olan bilgileri toplayın:
- Kimlik doğrulama seçeneklerini oluştururken oturumda sakladığınız beklenen giriş sorgulamasını alın.
- Beklenen kaynak 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 vardır:
- 1. Seçenek:
PublicKeyCredential
nesnesinderesponse.userHandle
öğesini kullanın. Kullanıcılar tablosundauserHandle
ile eşleşenpasskey_user_id
olup olmadığına bakın. - 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 arayın. Ardından, Kullanıcılar tablonuzapasskey_user_id
yabancı anahtarını kullanarak karşılık gelen kullanıcıyı bulun.
- 1. Seçenek:
- Aldığınız kimlik doğrulama onayıyla eşleşen ortak anahtar kimlik bilgisi bilgilerini veritabanınızda bulun. Bunu yapmak için Ortak anahtar kimlik bilgileri tablosunda,
PublicKeyCredential
nesnesindeid
bulunan kimlik bilgileriyle eşleşenid
kimlik bilgisini arayın.
Kimlik doğrulama onayını doğrulayın. Bu doğrulama adımını, genellikle bu amaç için bir yardımcı program işlevi sunacak olan FIDO sunucu tarafı kitaplığınıza aktarın. SimpleWebAuthn teklifleri (örneğin,
verifyAuthenticationResponse
). Ek: kimlik doğrulama yanıtının doğrulanması başlıklı makaleden, arka planda neler olduğunu öğrenebilirsiniz.Tekrar oynatma saldırılarını önlemek için doğrulama başarılı olsun veya olmasın, sorgulamayı silin.
Kullanıcının oturum açmasını sağlayın. Doğrulama başarılı olduysa kullanıcıyı oturum açmış olarak işaretlemek için oturum bilgilerini güncelleyin. Ayrıca, ön ucun yeni oturum açan kullanıcıyla ilişkili bilgileri kullanabilmesi için istemciye bir
user
nesnesi döndürmek isteyebilirsiniz.
Örnek kod: kullanıcıyı doğrulama ve oturum açma
Örneklerimizde SimpleWebAuthn kitaplığını kullanıyoruz. Bu bölümde, kimlik doğrulama yanıtının doğrulamasını, verifyAuthenticationResponse
işlevine devrediyoruz.
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:
- RP 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 bölümünü inceleyin.
- Cihazın, verdiğiniz giriş sorgulamasını yapabildiğinden emin olun.
- Kimlik doğrulama sırasında kullanıcının, kısıtlanmış taraf olarak zorunlu kıldığınız koşullara uyduğunu doğrulayın. Kullanıcı doğrulamasını zorunlu tutuyorsanız
authenticatorData
öğesindekiuv
(kullanıcı tarafından doğrulanmış) işaretinintrue
olduğundan emin olun. Geçiş anahtarları için kullanıcının varlığı her zaman gereklidir. Bu nedenleauthenticatorData
öğesindekiup
(kullanıcı mevcut) işaretinintrue
olduğundan emin olun. - İmzayı doğrulayın. İmzayı doğrulamak için ihtiyacınız olanlar:
- İmzalı sınama olan imza:
response.signature
- İmzayı doğrulamak için kullanılacak ortak anahtar.
- Orijinal imzalı veriler. Bunlar, imzası doğrulanacak verilerdir.
- İmzayı oluşturmak için kullanılan şifreleme algoritması.
- İmzalı sınama olan imza:
Bu adımlar hakkında daha fazla bilgi edinmek için SimpleWebAuthn'un verifyAuthenticationResponse
kaynak kodunu kontrol edin veya spesifikasyondaki doğrulamaların tam listesini inceleyin.