パスキーは、ユーザー アカウントの安全性、シンプルさ、使いやすさを高めます。
パスワードの代わりにパスキーを使用すると、ウェブサイトでのユーザー アカウントの安全性、シンプルさ、使いやすさを確保でき、パスワード不要の優れた方法を実現できます。パスキーを使用すると、ユーザーは指紋、顔認証、デバイスの PIN を使用するだけでウェブサイトやアプリにログインできます。
ユーザーがパスキーを使用してログインできるようにするには、ユーザー アカウントに関連付けられたパスキーを作成し、その公開鍵をサーバーに保存する必要があります。
仕組み
次のいずれかの状況では、ユーザーにパスキーの作成を求められることがあります。
- ユーザーがパスワードを使用してログインする場合。
- ユーザーが他のデバイスのパスキーを使用してログインした場合(つまり、
authenticatorAttachment
がcross-platform
)。 - ユーザーがパスキーを管理できる専用ページ。
パスキーを作成するには、WebAuthn API を使用します。
パスキー登録フローの 4 つのコンポーネントは次のとおりです。
- バックエンド: 公開鍵とパスキーに関するその他のメタデータを格納するアカウント データベースを保持するバックエンド サーバー。
- フロントエンド: ブラウザと通信し、バックエンドに取得リクエストを送信します。
- ブラウザ: JavaScript を実行しているユーザーのブラウザです。
- 認証システム: パスキーを作成して保存するユーザーの認証システム。これは、ブラウザと同じデバイス(Windows Hello を使用している場合など)の場合もあれば、スマートフォンなどの別のデバイスにある場合もあります。

既存のユーザー アカウントに新しいパスキーを追加する手順は次のとおりです。
- ユーザーがウェブサイトにログインします。
- ログインしたユーザーは、[パスキーを作成] ボタンを押すなどして、フロントエンドでパスキーの作成をリクエストします。
- フロントエンドは、ユーザー情報、チャレンジ、除外する認証情報 ID などのパスキーを作成するために、バックエンドに情報をリクエストします。
- フロントエンドが
navigator.credentials.create()
を呼び出してパスキーを作成します。この呼び出しは Promise を返します。 - ユーザーがデバイスの画面ロックを使用して同意すると、パスキーが作成されます。Promise が解決され、公開鍵認証情報がフロントエンドに返されます。
- フロントエンドは、公開鍵認証情報をバックエンドに送信し、今後の認証のために認証情報 ID とユーザー アカウントに関連付けられた公開鍵を保存します。
互換性
WebAuthn はほとんどのブラウザでサポートされていますが、若干のギャップがあります。パスキーの作成をサポートしているブラウザとオペレーティング システムの組み合わせについては、デバイスのサポート - passkeys.dev をご覧ください。
新しいパスキーを作成する
新しいパスキーの作成リクエストに対するフロントエンドの動作は次のとおりです。
特徴検出
[Create a new passkey] ボタンを表示する前に、次の点を確認してください。
- ブラウザは WebAuthn をサポートしています。
- デバイスがプラットフォーム認証システムをサポートしている(パスキーを作成し、パスキーで認証できる)。
- ブラウザは、WebAuthn 条件付き UI をサポートしています。
// Availability of `window.PublicKeyCredential` means WebAuthn is usable.
// `isUserVerifyingPlatformAuthenticatorAvailable` means the feature detection is usable.
// `isConditionalMediationAvailable` means the feature detection is usable.
if (window.PublicKeyCredential &&
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable &&
PublicKeyCredential.isConditionalMediationAvailable) {
// Check if user verifying platform authenticator is available.
Promise.all([
PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable(),
PublicKeyCredential.isConditionalMediationAvailable(),
]).then(results => {
if (results.every(r => r === true)) {
// Display "Create a new passkey" button
}
});
}
すべての条件が満たされるまで、このブラウザでパスキーはサポートされません。それまでは [新しいパスキーを作成] ボタンは表示されません。
バックエンドから重要な情報を取得する
ユーザーがボタンをクリックすると、重要な情報を取得してバックエンドから navigator.credentials.create()
を呼び出します。
challenge
: この登録のためにサーバーで生成されたチャレンジ(ArrayBuffer 内)。これは必須ですが、構成証明(ここでは扱いません)を行う場合を除き、登録時には使用されません。user.id
: ユーザーの一意の ID。この値は、メールアドレスやユーザー名などの個人を特定できる情報を含まない ArrayBuffer にする必要があります。アカウントごとに生成されるランダムな 16 バイトの値でも十分に機能します。user.name
: このフィールドには、メールアドレスやユーザー名など、ユーザーが認識できるアカウントの一意の識別子を格納します。これはアカウント選択画面に表示されます(ユーザー名を使用する場合はパスワード認証と同じ値を使用します)。user.displayName
: このフィールドは必須で、よりユーザー フレンドリーなアカウントの名前です。一意である必要はなく、ユーザーが選択した名前でも構いません。このフィールドに含めるのに適した値がサイトにない場合は、空の文字列を渡してください。ブラウザによってはアカウント選択画面に表示されますexcludeCredentials
: 登録済みの認証情報 ID のリストを提供することで、同じデバイスが登録されないようにします。transports
メンバーを指定する場合は、各認証情報の登録時にgetTransports()
を呼び出した結果が含まれている必要があります。
WebAuthn API を呼び出してパスキーを作成する
navigator.credentials.create()
を呼び出して新しいパスキーを作成します。API は Promise を返し、モーダル ダイアログを表示するユーザーの操作を待機します。
const publicKeyCredentialCreationOptions = {
challenge: *****,
rp: {
name: "Example",
id: "example.com",
},
user: {
id: *****,
name: "john78",
displayName: "John",
},
pubKeyCredParams: [{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}],
excludeCredentials: [{
id: *****,
type: 'public-key',
transports: ['internal'],
}],
authenticatorSelection: {
authenticatorAttachment: "platform",
requireResidentKey: true,
}
};
const credential = await navigator.credentials.create({
publicKey: publicKeyCredentialCreationOptions
});
// Encode and send the credential to the server for verification.
上記で説明されていないパラメータは次のとおりです。
rp.id
: RP ID はドメインであり、ウェブサイトでそのドメインまたは登録可能なサフィックスを指定できます。たとえば、RP の送信元がhttps://login.example.com:1337
の場合、RP ID はlogin.example.com
またはexample.com
のいずれかになります。RP ID がexample.com
として指定されている場合、ユーザーはlogin.example.com
またはexample.com
の任意のサブドメインで認証できます。rp.name
: RP の名前。pubKeyCredParams
: このフィールドには、RP でサポートされる公開鍵アルゴリズムを指定します。[{alg: -7, type: "public-key"},{alg: -257, type: "public-key"}]
に設定することをおすすめします。これは、P-256 と RSA PKCS#1 での ECDSA のサポートを指定し、これらをサポートすることで完全なカバレッジを提供します。authenticatorSelection.authenticatorAttachment
: このパスキーの作成がパスワードからのアップグレードである場合は、これを"platform"
に設定します(ログイン後のプロモーションなど)。"platform"
は、RP がプラットフォーム認証システム(プラットフォーム デバイスに埋め込まれた認証システム)を必要としており、USB セキュリティ キーなどの挿入を求めないことを示します。ユーザーはパスキーを簡単に作成できます。authenticatorSelection.requireResidentKey
: ブール値「true」に設定します。検出可能な認証情報(レジデントキー)は、ユーザー情報をパスキーに保存し、ユーザーが認証時にアカウントを選択できるようにします。authenticatorSelection.userVerification
: デバイスの画面ロックを使用するユーザー確認が、"required"
、"preferred"
、"discouraged"
のいずれであるかを示します。デフォルトは"preferred"
です。この場合、認証システムはユーザー確認をスキップできます。"preferred"
に設定するか、プロパティを省略します。
返された公開鍵認証情報をバックエンドに送信する
ユーザーがデバイスの画面ロックを使用して同意すると、パスキーが作成され、Promise が解決され、PublicKeyCredential オブジェクトがフロントエンドに返されます。
Promise はさまざまな理由で拒否されます。これらのエラーを処理するには、Error
オブジェクトの name
プロパティを確認します。
InvalidStateError
: パスキーはすでにデバイスに存在します。ユーザーにはエラー ダイアログは表示されず、サイトではこれをエラーとして扱うべきではありません。ユーザーがローカル デバイスを登録したいと考えていて、それが登録されています。NotAllowedError
: ユーザーがオペレーションをキャンセルしました。- その他の例外: 予期しないエラーが発生しました。ブラウザはユーザーにエラー ダイアログを表示します。
公開鍵認証情報オブジェクトには、次のプロパティが含まれています。
id
: 作成されたパスキーの、Base64URL でエンコードされた ID。この ID により、ブラウザは認証時に一致するパスキーがデバイス内にあるかどうかを判断できます。この値は、バックエンドのデータベースに保存する必要があります。rawId
: 認証情報 ID の ArrayBuffer バージョン。response.clientDataJSON
: ArrayBuffer でエンコードされたクライアント データ。response.attestationObject
: ArrayBuffer でエンコードされた構成証明オブジェクト。これには、RP ID、フラグ、公開鍵などの重要な情報が含まれます。authenticatorAttachment
: この認証情報がパスキー対応デバイスで作成されると、"platform"
を返します。type
: このフィールドは常に"public-key"
に設定されます。
ライブラリを使用して公開鍵認証情報オブジェクトをバックエンドで処理する場合は、オブジェクト全体を base64url で部分的にエンコードしてからバックエンドに送信することをおすすめします。
認証情報を保存する
バックエンドで公開鍵認証情報を受け取ったら、それを FIDO ライブラリに渡してオブジェクトを処理します。
その後、認証情報から取得した情報をデータベースに保存し、後で使用できます。以下に、保存する一般的なプロパティをいくつか示します。
- 認証情報 ID(主キー)
- ユーザー ID
- 公開鍵
公開鍵認証情報には、データベースに保存する次の情報も含まれています。
- バックアップ要件フラグ: デバイスがパスキー同期の対象である場合は
true
。 - Backup State フラグ:
true
(作成されたパスキーが実際に同期に設定されている場合)。 - トランスポート: デバイスがサポートするトランスポートのリスト。
"internal"
はデバイスがパスキーをサポートしていることを意味します。"hybrid"
は、別のデバイスでの認証もサポートしていることを意味します。
ユーザーを認証するには、フォームの自動入力でパスキーを使用してログインするをご覧ください。