パスキーなどの FIDO 認証情報はパスワードの置き換えを目的としていますが、その多くはユーザーがユーザー名を入力する手間を省くこともできます。これにより、ユーザーは現在のウェブサイトに対して持っているパスキーのリストからアカウントを選択して認証できます。
以前のバージョンのセキュリティ キーは 2 段階認証方式として設計されており、潜在的な認証情報の ID を必要とするため、ユーザー名の入力が必要でした。ID を知らなくてもセキュリティ キーが検出できる認証情報は、検出可能な認証情報と呼ばれます。現在作成された FIDO 認証情報のほとんどは検出可能な認証情報です。特に、パスワード マネージャーや最新のセキュリティ キーに保存されているパスキーです。
認証情報を確実に検出できるようにするには、パスキーの作成時に residentKey
と requireResidentKey
を指定します。
証明書利用者(RP)は、パスキー認証時に allowCredentials
を省略することで、検出可能な認証情報を使用できます。このような場合、ブラウザまたはシステムは、作成時に設定された user.name
プロパティによって識別される利用可能なパスキーのリストをユーザーに表示します。ユーザーがいずれかの値を選択すると、結果の署名に user.id
値が含まれます。サーバーは入力されたユーザー名の代わりに、返された認証情報 ID を使用してアカウントを検索できます。
前述のようなアカウント選択の UI には、検出できない認証情報は表示されません。
requireResidentKey
、residentKey
検出可能な認証情報を作成するには、navigator.credentials.create()
で authenticatorSelection.residentKey
と authenticatorSelection.requireResidentKey
を次のように指定します。
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 は navigator.credentials.get()
で allowCredentials
を使用してパスキー認証エクスペリエンスを制御できます。通常、パスキーの認証方法には次の 3 種類があります。
モーダル アカウント選択画面を表示する
検出可能な認証情報を使用すると、RP はモーダル アカウント セレクタを表示して、ログインに使用するアカウントをユーザーが選択し、ユーザー確認を行うことができます。これは、パスキー認証専用のボタンを押すことで開始されるパスキー認証フローに適しています。
このユーザー エクスペリエンスを実現するには、省略するか、navigator.credentials.get()
の allowCredentials
パラメータに空の配列を渡します。
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;
// ...
}
パスキー フォームの自動入力を表示する
上記のモーダル アカウント セレクタは、ほとんどのユーザーがパスキーを使用しており、ローカル デバイスでパスキーを利用できる場合に適しています。ローカル パスキーを持っていないユーザーでも、モーダル ダイアログが表示され、別のデバイスのパスキーを提示するよう求められます。ユーザーをパスキーに移行している間は、パスキーを設定していないユーザーには UI が表示されないようにすることをおすすめします。
代わりに、パスキーの選択内容が、保存済みのユーザー名とパスワードとともに、従来のログイン フォームのフィールドに自動入力されるプロンプトに組み込まれることがあります。このように、パスキーを持っているユーザーはパスキーを選択してログイン フォームに入力でき、ユーザー名とパスワードのペアが保存されているユーザーはそれらのペアを選択でき、どちらも持っていないユーザーはユーザー名とパスワードを入力できません。
このユーザー エクスペリエンスは、RP が移行中でパスワードとパスキーが混在している場合に最適です。
このユーザー エクスペリエンスを実現するには、allowCredentials
プロパティに空の配列を渡すか、パラメータを省略するほか、navigator.credentials.get()
に mediation: 'conditional'
を指定し、HTML の username
入力フィールドに autocomplete="username webauthn"
または password
入力フィールドに autocomplete="password webauthn"
アノテーションを付けます。
navigator.credentials.get()
を呼び出しても UI は表示されませんが、ユーザーがアノテーション付きの入力フィールドにフォーカスすると、使用可能なパスキーがすべて自動入力オプションに含まれます。ユーザーがこのオプションを選択すると、通常のデバイスのロック解除の確認が行われます。その後、.get()
から返された Promise が解決されて結果が返されます。ユーザーがパスキーを選択しない場合、Promise は解決されません。
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" ...>
このユーザー エクスペリエンスの構築方法については、フォームの自動入力でパスキーを使用してログインすると、ウェブアプリでフォームの自動入力を使用してパスキーを実装するの Codelab をご覧ください。
再認証
再認証にパスキーを使用する場合など、ユーザーの ID がすでにわかっている場合があります。ここでは、ブラウザや OS にアカウント選択画面が表示されることなくパスキーを使用します。これを行うには、allowCredentials
パラメータに認証情報 ID のリストを渡します。
指定した認証情報のいずれかがローカルで使用できる場合は、すぐにデバイスのロック解除を求めるメッセージが表示されます。ログインしていない場合、ユーザーは有効な認証情報を保持する別のデバイス(スマートフォンまたはセキュリティ キー)を提示するよう求められます。
このユーザー エクスペリエンスを実現するために、ログイン ユーザーの認証情報 ID のリストを提供します。ユーザーはすでに知っているため、RP はユーザーにクエリを実行できるはずです。navigator.credentials.get()
の allowCredentials
プロパティで、認証情報 ID を PublicKeyCredentialDescriptor
オブジェクトとして指定します。
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 がパスキー登録で取得した公開鍵認証情報の ID。type
: 通常、このフィールドは'public-key'
です。transports
: この認証情報を保持するデバイスでサポートされているトランスポートのヒント。ユーザーに外部デバイスを表示するよう求める UI を最適化するためにブラウザで使用されます。このリストには、各認証情報の登録時にgetTransports()
を呼び出した結果が含まれている必要があります。
まとめ
認証情報が検出されると、ユーザー名の入力を省略できるようになるため、パスキーのログイン エクスペリエンスが大幅に向上します。residentKey
、requireResidentKey
、allowCredentials
を組み合わせることで、RP は次のようなログイン エクスペリエンスを実現できます。
- モーダル アカウント選択ツールを表示します。
- パスキー フォームの自動入力を表示します。
- 再認証。
検出可能な認証情報を適切に使用します。そうすることで、ユーザーがシームレスで利用しやすいと感じる洗練されたパスキーのログイン エクスペリエンスをデザインできます。