در حالی که اعتبارنامه های FIDO مانند کلیدهای عبور جایگزین رمز عبور هستند، اکثر آنها همچنین می توانند کاربر را از تایپ نام کاربری آزاد کنند. این به کاربران امکان میدهد تا با انتخاب یک حساب کاربری از فهرست کلیدهای عبوری که برای وبسایت فعلی دارند، احراز هویت کنند.
نسخههای قبلی کلیدهای امنیتی بهعنوان روشهای احراز هویت دو مرحلهای طراحی شده بودند و به شناسههای اعتبار بالقوه نیاز داشتند، بنابراین نیاز به وارد کردن نام کاربری داشتند. اعتبارنامه هایی که یک کلید امنیتی می تواند بدون اطلاع از شناسه آنها پیدا کند، اعتبار قابل کشف نامیده می شود. اکثر اعتبارنامه های FIDO که امروزه ایجاد می شوند، اعتبارنامه های قابل کشف هستند. به ویژه کلیدهای عبور ذخیره شده در یک مدیر رمز عبور یا در یک کلید امنیتی مدرن.
برای اطمینان از اینکه اعتبارنامههای شما بهعنوان کلیدهای عبور (مدارک شناسایی قابل کشف) ایجاد میشوند، هنگام ایجاد اعتبار residentKey
و requireResidentKey
مشخص کنید.
احزاب متکی (RPs) میتوانند از اعتبارنامههای قابل کشف با حذف allowCredentials
در طول احراز هویت رمز عبور استفاده کنند. در این موارد، مرورگر یا سیستم فهرستی از کلیدهای عبور موجود را به کاربر نشان میدهد که توسط ویژگی user.name
تنظیم شده در زمان ایجاد مشخص شده است. اگر کاربر یکی را انتخاب کند، مقدار user.id
در امضای حاصل گنجانده می شود. سپس سرور می تواند از آن یا شناسه اعتبار برگشتی برای جستجوی حساب به جای نام کاربری تایپ شده استفاده کند.
رابطهای کاربری انتخابگر حساب، مانند مواردی که قبلاً توضیح داده شد، هرگز اعتبار غیرقابل کشف را نشان نمیدهند.
requireResidentKey
و residentKey
برای ایجاد یک رمز عبور، authenticatorSelection.residentKey
و authenticatorSelection.requireResidentKey
در navigator.credentials.create()
با مقادیر نشان داده شده به صورت زیر مشخص کنید.
async function register () {
// ...
const publicKeyCredentialCreationOptions = {
// ...
authenticatorSelection: {
authenticatorAttachment: 'platform',
residentKey: 'required',
requireResidentKey: true,
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
residentKey
:
-
'required'
: یک اعتبار قابل کشف باید ایجاد شود. اگر نمی توان آن را ایجاد کرد،NotSupportedError
برگردانده می شود. -
'preferred'
: RP ترجیح می دهد یک اعتبار قابل کشف ایجاد کند، اما یک اعتبار غیر قابل کشف را می پذیرد. -
'discouraged'
: RP ترجیح می دهد یک اعتبار غیرقابل کشف ایجاد کند، اما یک اعتبار قابل کشف را می پذیرد.
requireResidentKey
:
- این ویژگی برای سازگاری با عقب از WebAuthn Level 1، نسخه قدیمیتری از مشخصات، حفظ شده است. اگر
residentKey
'required'
این را رویtrue
تنظیم کنید، در غیر این صورت آن را رویfalse
تنظیم کنید.
allowCredentials
RP ها می توانند از allowCredentials
در navigator.credentials.get()
برای کنترل تجربه احراز هویت با کلید عبور استفاده کنند. معمولاً سه نوع تجربه احراز هویت وجود دارد:
یک انتخابگر حساب معین نشان دهید
با اعتبارنامه های قابل کشف، RP ها می توانند یک انتخابگر حساب معین را به کاربر نشان دهند تا یک حساب کاربری را برای ورود به سیستم انتخاب کند و سپس تأیید کاربر را انجام دهد. این برای جریان احراز هویت با کلید عبور که با فشار دادن دکمه ای که به احراز هویت رمز عبور اختصاص داده شده است، مناسب است.
برای دستیابی به این تجربه کاربری، یک آرایه خالی را به پارامتر allowCredentials
در navigator.credentials.get()
حذف یا ارسال کنید.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
تکمیل خودکار فرم کلید رمز را نشان دهید
اگر اکثر کاربران از کلیدهای عبور استفاده کنند و آنها را در دستگاه محلی در دسترس داشته باشند، انتخابگر حساب معین که در بالا توضیح داده شد، به خوبی کار می کند. برای کاربری که کلیدهای عبور محلی ندارد، کادر محاورهای مدال همچنان ظاهر میشود و به کاربر پیشنهاد میدهد یک کلید عبور از دستگاه دیگری ارائه کند. هنگام انتقال کاربران خود به کلیدهای عبور، ممکن است بخواهید از این رابط کاربری برای کاربرانی که یکی را راهاندازی نکردهاند اجتناب کنید.
درعوض، انتخاب یک کلید عبور ممکن است در اعلانهای تکمیل خودکار فیلدها در فرم ورود به سیستم سنتی، در کنار نامهای کاربری و رمزهای عبور ذخیرهشده قرار گیرد. به این ترتیب، کاربر با کلیدهای عبور میتواند با انتخاب کلید عبور خود، فرم ورود به سیستم را پر کند، کاربرانی که جفتهای نام کاربری/رمز عبور ذخیرهشده دارند، میتوانند آنها را انتخاب کنند، و کاربرانی که هیچ کدام از آنها را ندارند همچنان میتوانند نام کاربری و رمز عبور خود را تایپ کنند.
این تجربه کاربری زمانی ایده آل است که RP تحت یک مهاجرت با استفاده ترکیبی از رمزهای عبور و کلیدهای عبور باشد.
برای دستیابی به این تجربه کاربری، علاوه بر ارسال یک آرایه خالی به ویژگی allowCredentials
یا حذف پارامتر، mediation را در navigator.credentials.get()
مشخص کنید mediation: 'conditional'
و یک فیلد ورودی username
HTML را با autocomplete="username webauthn"
یا حاشیه نویسی کنید. یک فیلد ورودی password
با autocomplete="password webauthn"
.
فراخوانی به navigator.credentials.get()
باعث نمیشود که هیچ رابط کاربری نشان داده شود، اما اگر کاربر روی فیلد ورودی مشروح تمرکز کند، کلیدهای عبور موجود در گزینههای تکمیل خودکار گنجانده میشود. اگر کاربر یکی را انتخاب کند، از طریق تأیید باز کردن قفل دستگاه معمولی می گذرد، و تنها در این صورت وعده ای که توسط .get()
بازگردانده شده است با نتیجه حل می شود. اگر کاربر رمز عبور را انتخاب نکند، وعده هرگز حل نمی شود.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// You can omit `allowCredentials` as well:
allowCredentials: []
};
const cred = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal,
// Specify 'conditional' to activate conditional UI
mediation: 'conditional'
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
<input type="text" name="username" autocomplete="username webauthn" ...>
میتوانید نحوه ایجاد این تجربه کاربری را در ورود به سیستم با کلید عبور از طریق تکمیل خودکار فرم و همچنین پیادهسازی کلیدهای عبور با تکمیل خودکار فرم در یک کد برنامه وب یاد بگیرید.
احراز هویت مجدد
در برخی موارد، مانند هنگام استفاده از کلیدهای عبور برای احراز هویت مجدد، شناسه کاربر از قبل شناخته شده است. در این مورد، مایلیم بدون اینکه مرورگر یا سیستم عامل هیچ شکلی از انتخابگر حساب را نشان دهد، از یک رمز عبور استفاده کنیم. این را می توان با ارسال لیستی از شناسه های اعتبار در پارامتر allowCredentials
به دست آورد.
در آن صورت، اگر هر یک از اعتبارنامههای نامگذاری شده به صورت محلی در دسترس باشد، از کاربر خواسته میشود که بلافاصله قفل دستگاه را باز کند. در غیر این صورت، از کاربر خواسته می شود دستگاه دیگری (تلفن یا کلید امنیتی) که دارای اعتبار معتبر است را ارائه دهد.
برای دستیابی به این تجربه کاربری، فهرستی از شناسه های اعتبار را برای کاربر وارد شده ارائه دهید. RP باید بتواند آنها را پرس و جو کند زیرا کاربر از قبل شناخته شده است. شناسه های اعتبار را به عنوان اشیاء PublicKeyCredentialDescriptor
در ویژگی allowCredentials
در navigator.credentials.get()
ارائه کنید.
async function authenticate() {
// ...
const publicKeyCredentialRequestOptions = {
// Server generated challenge:
challenge: ****,
// The same RP ID as used during registration:
rpId: 'example.com',
// Provide a list of PublicKeyCredentialDescriptors:
allowCredentials: [{
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, {
id: ****,
type: 'public-key',
transports: [
'internal',
'hybrid'
]
}, ...]
};
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
signal: abortController.signal
});
// This does not run until the user selects a passkey.
const credential = {};
credential.id = cred.id;
credential.rawId = cred.id; // Pass a Base64URL encoded ID string.
credential.type = cred.type;
// ...
}
یک شی PublicKeyCredentialDescriptor
شامل موارد زیر است:
-
id
: شناسه ای از اعتبار کلید عمومی که RP در ثبت کلید عبور به دست آورده است. -
type
: این فیلد معمولاً'public-key'
است. -
transports
: اشاره ای به حمل و نقل های پشتیبانی شده توسط دستگاه دارای این اعتبار، که توسط مرورگرها برای بهینه سازی رابط کاربری استفاده می شود که از کاربر می خواهد یک دستگاه خارجی ارائه دهد. این لیست، در صورت ارائه، باید حاوی نتیجه فراخوانیgetTransports()
در هنگام ثبت هر اعتبار باشد.
خلاصه
اعتبارنامههای قابل کشف، تجربه ورود با رمز عبور را بسیار کاربرپسندتر میکنند و به آنها اجازه میدهد از وارد کردن نام کاربری خودداری کنند. با ترکیب residentKey
، requireResidentKey
، و allowCredentials
، RP ها می توانند به تجربیات ورود به سیستم دست یابند که:
- یک انتخابگر حساب معین نشان دهید.
- تکمیل خودکار فرم کلید رمز را نشان دهید.
- احراز هویت مجدد
از اعتبارنامه های قابل کشف عاقلانه استفاده کنید. با انجام این کار، میتوانید تجربههای پیچیدهای برای ورود با کلید عبور طراحی کنید که کاربران بینظیر آن را بیابند و احتمال بیشتری برای تعامل با آنها داشته باشند.