パスキー
パスキーを利用すると、ウェブサイトは、ユーザーがサイト上でパスワードやその他の秘密のコードを入力することなく、ユーザーを認証することができます。パスキーは、パスワードなど他の認証方法に見られる最も深刻な弱点の多くを解決します。
パスキーは、共有された秘密情報ではなく、公開鍵暗号を利用します。パスキーとは、具体的なウェブサイト上の具体的なユーザーアカウントに紐付けられた公開鍵・秘密鍵のペアのことです。
秘密鍵は、認証器 (authenticator) と呼ばれるモジュールに格納されており、これはユーザーの端末に内蔵されているか、または添付されています。認証器は、プラットフォームに組み込まれていたり、YubiKey のような別個のハードウェアキーであったり、KeePassXC のような資格情報管理アプリであったりします。
公開鍵はウェブサイトのサーバーに格納されます。ユーザーがログインする際、認証器は秘密鍵を使用して、サーバーから送信されたチャレンジの値に、リクエスト元のオリジンなどのコンテキスト情報を加えてデジタル署名を行います。その結果生成されるオブジェクトは「アサーション」と呼ばれます。ウェブサイトのサーバーは公開鍵を使用してアサーションの署名を検証し、ユーザーをログインさせることができます。
このガイドでは、以下の内容を取り上げます。
- ウェブアプリがパスキーを使用することができるウェブ認証 API (WebAuthn) について紹介します。
- WebAuthn が対応している 2 つの主要な手続き、登録とログインについて説明します。
- ウェブ認証 APIの主な機能のいくつかを紹介します。
- パスキーのセキュリティ特性をまとめます。
- ユーザーがパスキーを紛失した場合にロックアウトされないように役立つベストプラクティス、ユーザーがパスキーを管理するためのベストプラクティス、およびユーザーがパスワードから移行するためのベストプラクティスについて探ります。
ウェブ認証 API
認証器とやり取りを行うため、ウェブサイトではウェブ認証 API (WebAuthn) が使用されます。WebAuthn 仕様書では、パスキーを使用してユーザーを認証するウェブサイトを認証依頼者 (RP) と呼びますが、本ガイドでもこの用語を使用します。
WebAuthn は、資格情報管理 APIの拡張機能であり、資格情報を管理するためのフレームワークであり、パスワードや連合アイデンティティ、さらにはパスキーなどを含む、様々な認証方式に対応しています。
RP が使用する主な機能は、次の 2 つです。
CredentialsContainer.create()。これは、ユーザーがサイトに登録する際に新しいパスキーを作成するために使用します。CredentialsContainer.get()。これは、ユーザーがサイトにログインした際に、ユーザーの格納されたパスキーからアサーションを生成するために使用されます。
登録
この節では、新しいパスキーを作成し、それを使用して新しいユーザーアカウントを設定する手順を追ってみましょう。
ユーザーがサイトへの登録をリクエストすると、RP のフロントエンドコードはまず、サーバーにチャレンジを要求します。これはサーバー上で生成されたランダムな値であり、サーバーは後でこれを使用して、生成されたパスキーがこのリクエストに応じて生成されたものであることを確認します。
次に、RP のフロントエンドコードが CredentialsContainer.create() を呼び出します。これは、以下のようなさまざまなオプションを指定することができます。
-
アテステーション設定: RP が認証器に対するアテステーション(RP が認証器を信頼すべきかどうかを判断するための仕組み)に関心を持っているかどうか、また、関心がある場合、そのアテステーションはどのような形式をとるべきか。
-
ウェブサイトの情報: 新しいパスキーに関連付けられる RP の、人間が読み取り可能な名前と ID です。この ID によって、生成されるパスキーのスコープが決まります。
-
ユーザー情報: 新しいパスキーに関連付けられるユーザーに関する情報です。これには、人間が読み取れる表示名、アカウント識別子、およびメールアドレスやユーザー名などの人間が読み取れるアカウント識別子が含まれます。
認証器の機能や RP の設定によっては、認証器がユーザーに対し、何らかのユーザー認証方法(例えば、指紋などの生体認証)を用いてパスキーの作成を承認するよう依頼する場合があります。
その後、認証器はアカウント用のパスキーを生成します。認証器は秘密鍵をローカルに格納し、公開鍵、チャレンジ、およびその他の情報を含むオブジェクトを返します。認証器がアテステーションを実行している場合、これらはすべて、認証器が所有する秘密鍵またはアテステーションキーのどちらかを使用してデジタル署名されます。
RP のフロントエンドコードはこれをサーバーに送信し、サーバーは次の処理を行います。
- アテステーションが行われている場合、そのアテステーションを検証します
- チャレンジが期待される値であるかを確認します
- 新しいユーザーアカウントを作成し、そのアカウント情報とともに公開鍵を格納します。
ログイン
この節では、パスキーを使用してユーザーをログインさせる手順を追ってみましょう。
ユーザーがログインしようとすると、RP のフロントエンドコードは再びサーバーにチャレンジ値を尋ねます。
次に、RP のフロントエンドコードが CredentialsContainer.get() を呼び出します。これでは、以下のようなさまざまなオプションを指定することができます。
-
許可された資格情報: RP が受け入れるパスキーの識別子の配列です。この配列は空でも、省略してもかまいません。その場合、適切なパスキーであればどれでも使用できます。
-
チャレンジ: RP のサーバーによって生成されたチャレンジ。
-
ウェブサイト ID: ユーザーをログインさせようとしている RP の ID です。パスキーのスコープを参照してください。
-
ユーザー検証: 認証器が、パスキーを使用する前にユーザー認証を行うべきかどうか。
次に、ブラウザーは指定された条件に一致するパスキーを検索します。複数のパスキーが見つかった場合、ユーザーに選択を求めることがあります。このパスキーを格納している認証器は、通常、ユーザーに対してこのパスキーの使用を承認するよう依頼します。これには、RPからリクエストがあり、かつ認証器が対応している場合、ユーザー認証も記載します。
その後、認証器はパスキーの秘密鍵を使用して、チャレンジやその他のデータを含む、デジタル署名付きのアサーションを作成します。
RP のフロントエンドはアサーションをサーバーに送信し、サーバーは格納されている公開鍵を使用して署名を検証します。検証が成功すれば、ユーザーはログインできます。
ウェブ認証の特徴
この節では、ウェブ認証 API のさまざまな側面について、さらに詳しく解説します。
プラットフォーム認証器とローミング認証器
ウェブ認証 API は、2 種類の認証器を区別します。
- プラットフォーム認証器
-
これらの認証器は、端末から取り外すことができません。例えば、Apple 製端末の Touch ID や Windows Hello のように、端末のオペレーティングシステムに組み込まれている認証器などが該当します。
- ローミング認証器
-
これらの認証器は、現在の端末から取り外し、別の端末に取り付けることが可能です。その代表的な例として、YubiKey のような USB キーとして実装された認証器が挙げられます。
RP が新しいパスキーを生成する際、CredentialsContainer.create() に渡す authenticatorSelection オプションの一部として、使用する認証器のタイプを指定することができます。
プラットフォーム認証器の主な利点は、ユーザーにとって便利であるという点です。別個のハードウェアを管理する必要がありません。主な欠点は、ホストデバイスでしか使用できないことです。
プラットフォーム認証器は、場合によってはローミング認証器として機能することがあります。例えば、モバイル端末上のプラットフォーム認証器が、Bluetooth 接続を介してノートパソコンでローミング認証器として利用できることがあります。
プラットフォーム認証器は端末から取り外せませんが、通常はクラウド同期やインポート/エクスポート機能を通じて、他の認証器とパスキーを共有することができます。例えば、プラットフォームプロバイダーは、ユーザーが自社製品ファミリーに属するすべての端末間でパスキーを共有することができる場合があります。
検出可能な資格情報と検出不可能な資格情報
WebAuthn 仕様書では、検出可能な資格情報と検出不可能な資格情報を区別しています。
-
検出可能な資格情報は「常駐キー」とも呼ばれ、RP が認証対象のユーザーを事前に特定する必要がなく、使用することができます。つまり、
CredentialsContainer.get()に「許可された資格情報」の配列が渡された場合、空であっても構いません。検出可能な資格情報の場合、すべての署名鍵データは認証器内に格納されているため、認証器はRPからの入力を必要とせずに署名を生成することができます。 -
検出不可能な資格情報は「非常駐キー」とも呼ばれ、RP が認証対象のユーザーを事前に特定しなければならず(例えば、ユーザー名を入力させるなど)、その後、関連付けられた資格情報 ID を「許可された資格情報」配列内の
CredentialsContainer.get()に渡す必要があるものです。検出不可能な資格情報には、資格情報 ID が必要です。これは、資格情報自体に署名鍵を格納せず、必要な都度、内部のシードと資格情報 ID の値から署名鍵を生成するためです。つまり、アカウント鍵は認証器内に常駐していません。
検出不可能な資格情報を使用する利点は、それぞれのアカウントの鍵情報が認証器に格納されないため、ストレージ容量が限られている認証器でも、事実上無制限の数のアカウントに対応できる点にあります。
検出可能な資格情報を使用する利点は、ブラウザーが公開鍵資格情報による自動入力機能を実装することができることであり、これにより、特に指定されたサイトに対して公開鍵資格情報とパスワードの両方を持つことができる場合、ユーザーがログインしやすくなります。
このため、パスキーは常に検出可能な資格情報でなければなりません。したがって、パスキーベースの認証を実装する RP は、常にパスキーを検出可能にする必要があります。
検出可能な資格情報を作成するには、RP は CredentialsContainer.create() の呼び出しで新しい資格情報を作成する際、residentKey オプションを "required" に、requireResidentKey オプションを true に設定する必要があります。
チャレンジ
RP が認証器に対して新しいパスキーの生成や既存のパスキーの使用を依頼する際は、チャレンジを提供する必要があります。これはリクエスト固有のランダムな値であり、攻撃者が予測できないものでなければなりません。チャレンジは信頼できる環境(一般的にはフロントエンドではなくサーバー側)で生成される必要があります。
RP のフロントエンドコードは、このチャレンジを create() または get() の呼び出しに渡します。そして、ブラウザーはこれらのメソッドから返されるオブジェクトに同じ値を記載します。get() の場合、チャレンジ値は、認証器が計算するデジタル署名の入力の一部にもなります。
ウェブサーバーが認証器からのレスポンスを検証する際、ウェブサーバーは、指定されたチャレンジ値が当初指定した値と同じであることを調べる必要があります。
また、ウェブサーバーは、約 10 分後にチャレンジ値を無効化し、この時点以降に届いたチャレンジ値を含むレスポンスはすべて拒否する必要があります。
このチャレンジは、認証器からのレスポンスがこのリクエストに対するものであり、攻撃者が何らかの方法で盗み出した以前のリクエストに対する古いレスポンスではないことを証明するものです。この種の攻撃は、リプレイ攻撃と呼ばれています。
アテステーション
パスキーのセキュリティは、使用する認証器の信頼性に一部依存しています。例えば、認証器が秘密鍵を適切に保護していない場合、攻撃者が鍵を盗み出し、ユーザーになりすます可能性があります。ウェブ認証では、アテステーションと呼ばれるオプションのメカニズムが定義されています。これによって、認証器は、自身および生成したデータ(鍵ペアや署名付きアサーションなど)に関する検証可能な証拠を RP に提供できます。これにより、RP は、ユーザーの認証にその認証器に頼っているかどうかを判断する際に役立ちます。
認証機能を実装するため、認証器には「認証キー」と呼ばれる鍵ペアが含まれています。これは製造時に端末に組み込まれており、この認証器を製造した組織に属するものであることが認証されています。例えば、証明書には、この認証器が "Acme Authenticator Incorporated" によって製造されたことが記載されている場合があります。
認証器が新しいパスキーを生成する際、その生成されたオブジェクトに自身のアテステーション鍵を用いて署名を行います。RPは署名と関連付けられた証明書を検証し、その結果、そのパスキーが "Acme Authenticator Incorporated" 製の認証器によって生成されたものであるという証拠を得ることができます。
すべての認証器がアテステーション機能に対応しているわけではなく、RP 側がアテステーションに関心がないことを示す場合もあります。このような状況では、CredentialsContainer.create() の呼び出しによって返されるオブジェクトは、まったく署名されていないか、あるいはパスキー自体を使用して署名されている場合があります(これは自己アテステーションと呼ばれます)。このような状況では、RP は認証器の出所や機能に関する信頼できる証拠を持ちません。
ユーザー検証
ウェブサイトが新しいパスキーを作成するために CredentialsContainer.create() を呼び出したり、アサーションを作成するために CredentialsContainer.get() を呼び出したりすると、認証器は常にユーザーにその操作への同意を依頼します。
RPは、認証器に対してユーザー認証を実行するよう依頼することもできます。これは、ユーザーに対して、PIN の入力や指紋などの生体認証を行うなどして、自身の資格情報の使用を承認するよう求めることを意味します。
この場合、これは多要素認証という形で現れます。認証器そのものが「ユーザーが持っているもの」であり、PIN や生体認証はそれぞれ「ユーザーが知っているもの」および「ユーザーそのもの」にあたります。
なお、すべての認証器がユーザー検証に対応しているわけではありません。
パスキーのスコープ
パスキーのスコープによって、どのサイトでそのパスキーを使用することができるかが決まります。
デフォルトでは、
-
ページが
CredentialsContainer.create()を呼び出してパスキーを生成すると、ブラウザーはパスキーの RP ID を呼び出し側のオリジンのドメイン部分として設定し、認証器はこの値をパスキーと共に格納します。 -
ページが
CredentialsContainer.get()を呼び出してパスキーを使用する場合、ブラウザーは呼び出し側のオリジンのドメイン要素を認証器に渡します。そして、認証器は、この値が格納されている RP ID と一致する場合にのみ、パスキーの使用を許可します。
つまり、デフォルトで、パスキーは、それを最初に作成したページと同じオリジン(ポート番号を除く)にあるページでのみ使用できます。
ウェブサイトは、一定の制約の範囲内で、これらのルールを緩和することが可能です。
-
ウェブサイトがパスキーを作成する際、
CredentialsContainer.create()に ID を渡すことができます。そうすると、認証器はこの ID を RP ID として使用します。 -
同様に、ウェブサイトがパスキーを使用しようとするときは、
CredentialsContainer.get()に ID を渡すことができ、認証器はこの ID を格納されている RP ID と照合します。
create() と get() の両方において、渡される値は、呼び出し側のオリジンに属するドメインのドメイン接尾辞である登録可能なドメインでなければなりません。
この緩和措置では、例えば、https://register.example.com のページが RP ID が example.com のパスキーを作成した場合、https://login.example.com のページはそのパスキーを使用することができることになります。
パスキーのスコープは、フィッシング攻撃からの防御に役立ちます。フィッシング攻撃では、ユーザーに対して、標的となるサイトに見せかけた悪意のあるページが表示され、そのサイトへの資格情報の入力が依頼されます。通常、悪意のあるサイトの URL は標的となるサイトの URL と似せて作られており、ユーザーを惑わすようになっています。例えば、標的となるサイトが https://example.com である場合、フィッシングサイトは https://examp1e.com から配信されることがあります。
ただし、パスキーのスコープに関するルールにより、https://examp1e.com から提供されるサイトでは、https://example.com 用に作成されたパスキーを使用することはできません。
オリジン検証
認証器が返す署名付きアサーションには、呼び出し側のコンテキストに関する情報が記載されています。
CredentialsContainer.get()を呼び出した文書のオリジン。- 呼び出し側が
<iframe>として埋め込まれていた場合、呼び出し側が最上位文書と同一オリジンを持っていたかどうか。 - 呼び出し側が
<iframe>として埋め込まれており、かつ呼び出し側と同一オリジンではなかった場合、最上位文書のオリジン。
RP サーバーがアサーションを検証する際は、これらの値が期待される値と一致しているかを調べなければならない。
パスキーのセキュリティ特性
パスキーはパスワードよりも安全であり、その設計がパスワードの最も深刻な弱点をどのように解決しているかがわかります。
-
パスワードとは異なり、ユーザーがパスキーの値を自分で作成したり、それを記憶したりする必要はありません。つまり、ユーザーが脆弱なパスキーを選択することはできないため、推測攻撃の標的になることはありません。パスキーの生成は、ユーザーから認証器へと移管されます。
-
パスキーはサイト間で再利用されることがありませんので、資格情報流用攻撃の被害を受けることはありません。攻撃者がパスキーを取得したとしても、それを使用できるのは、そのパスキーが作成された元のサイトに限定されます。
-
パスキーを使用すれば、サーバーは秘密鍵を一切格納する必要がありません。格納するのは公開鍵のみです。したがって、攻撃者がサーバーのデータベースに侵入したとしても、認証器に格納されている秘密鍵を盗み出すことはできません。ただし、攻撃者がサーバーのデータベースに偽の資格情報を書き込むことが可能であれば、ユーザーアカウントを乗っ取ることができる点には注意が必要です。
-
ユーザーがログインしようとすると、ブラウザーはリクエスト元のサイトとスコープが一致するパスキーのみを見ていき、RP のサーバーはリクエスト元のオリジンが想定通りであることを確認できます。これにより、パスキーはフィッシング攻撃に対して耐性を持つようになります。
https://examp1e.comのようなフィッシングサイトから提供されるフロントエンドコードは、https://example.comに関連付けられたパスキーを使用できないからです。
パスキーは、こうした一般的なウェブ認証攻撃に対する防御策となりますが、すべての脅威を排除できるわけではありません。パスキーの広範な展開は比較的新しいことであるため、パスキーが直面しうる攻撃について、まだ十分に理解が進んでいません。しかし、ユーザーの端末を標的とした攻撃、例えば、悪意のある認証器をインストールさせるような攻撃が行われる可能性は高いと考えられます。また、アカウント復旧の手続きなど、パスキーによって保護されていない認証システムの一部が攻撃の標的となる可能性もあります。
パスキーの紛失時の扱い
ユーザーが認証器(別個のモジュールであれ、スマートフォンに組み込まれたものであれ)を紛失した場合、その認証器に含まれているすべてのパスキーを失うことになります。
この節では、認証器の紛失に対処するための 2 つの方法について説明します。
複数のパスキーの作成
パスワードに関するアドバイスとは対照的に、RP (リソースプロバイダー)に対しては、単一のアカウントに対して複数のパスキーを作成することが推奨されています。一般的なパターンとしては、次のようなものが挙げられます。
- プラットフォーム認証器に保存された 1 つのパスキー。これは、そのサイトでの日常的なパスキーとなります
- ローミング認証器に保存された 1 つのパスキー。これは、端末を紛失した場合のバックアップとして、ユーザーが安全な場所に保管しておくものです。
CredentialsContainer.create() に渡される excludeCredentials オプションは、資格情報の ID を列挙し、掲載されている鍵が含まれている認証器を新しい鍵の作成に使用してはならないことをブラウザーに指示します。つまり、これは RP が新しいパスキーを新しい認証器で確実に生成する方法を示します。
パスキーのバックアップ
一部の認証器では、クラウド同期や手動でのエクスポートなど、さまざまな方法によるバックアップに対応しています。get() の呼び出しによって返される署名付きウェブ認証アサーションには、一連のフラグが記載されており、これらはとりわけ、パスキーが以下のいずれかに該当するかどうかを示します:
- バックアップの対象となるか。つまり、バックアップに対応した認証器に格納されているかどうか
- 実際にバックアップされているか。
RPはこの情報を使用して、ユーザーが資格情報を管理できるよう役立つ支援を行うことができます。例えば、
-
パスキーがバックアップの対象外である場合、RP は、バックアップとして使用できる別の認証器で新たなパスキーを作成するよう、ユーザーに促す応答を行うことがあります。
-
RP がユーザーをパスワードから移行させようとしており、ユーザーが古いパスワードとパスキーの両方を持っていて、かつアサーションでパスキーがバックアップされていることが示されている場合、RP は、バックアップとしてもう必要ないため、ユーザーに古いパスワードを削除するよう促すことがあります。
パスキーの管理
ユーザーが単一のアカウントに対して複数のパスキーを持ち、それらが複数の認証器や端末に分散していることがあることが分かりました。それぞれのパスキーは WebAuthn 資格情報に対応しており、秘密鍵は認証器によって保護され、対応する公開鍵は RP によってユーザーのアカウント情報の一部として格納されます。
ユーザーが RP アカウントのパスキーを削除する必要が生じる場合があります。これは本質的に、RP のサーバーに格納されている公開鍵を削除することを意味し、それによって対応する秘密鍵がユーザーのログインに利用できなくなります。これは一般的に、ユーザーが認証器を紛失するなどして、もはやその管理権限を持たなくなった場合に必要となります。
つまり、RP は、認証済みのユーザーが自身のアカウントに登録されたパスキーを確認し、特定の公開鍵を削除できる手段を実装する必要があります。それぞれの鍵について、RP は、それがどの鍵であり、どの認証器に関連付けられているかをユーザーが理解できるよう、役立つ情報を表示させる必要があります。これには以下のものを含めることができます。
-
パスキーのプロバイダー名: "Windows Hello" や "Bitwarden" など、パスキープロバイダーの名前です。
メモ: この値を算出するには、次のようにします。
CredentialsContainer.create()の呼び出しが成功した際に、ブラウザーから返されるattestedCredentialDataの中から、AAGUID の値を探してください。- これを使用して、Passkey Provider AAGUIDs のリストから対応する名前を検索してください。
Determine the passkey provider with AAGUID も確認してください。
-
タイムスタンプ: パスキーが最後にログインに使用された時刻です。
-
バックアップ状態:パスキーがバックアップされているかどうかを示すインジケーターです(パスキーのバックアップを参照してください)。
さらに、ユーザーはパスキーの名前を変更したり、パスキーを削除したりできる必要があります。
ユーザーが最後のパスキーを削除しようとした場合、RP はその影響についてユーザーに通知する必要があります。RP によっては、ワンタイムコードなどの別の方法でログインすることができる場合もありますが、それ以降アカウントにアクセスできなくなる場合もあります。
Help users manage passkeys effectively も参照してください。
サーバーと認証器の同期
ユーザーが RP のサーバー上でパスキーを削除した場合、サーバーと、対応する秘密鍵が含まれている認証器との間に不整合が生じることに注意してください。認証器はその後もパスキーが有効であると認識しているため、ブラウザーはユーザーにログインオプションとしてそれを提示することがありますが、RPはそのアサーションを受け入れることができなくなります。
このような問題が発生する可能性を減らすため、ウェブ認証 API は PublicKeyCredential の静的メソッド群を定義しており、これにより RP はサーバー側の変更を認証器に指示できるようになります。
-
PublicKeyCredential.signalUnknownCredential()は、特定のパスキーが RP によって認識されなかったことをブラウザーに伝えるものであり、通常、ユーザーがこのパスキーでログインを試みた後、RP が呼び出します。もっともよくある場面は、ユーザーがサーバー上でこのパスキーを削除した後、誤ってそのパスキーを使用してログインを試みた場合です。 -
PublicKeyCredential.signalAllAcceptedCredentials()は、RP が現在有効として受け入れているすべてのパスキーの識別子をブラウザーに通知し、添付されているすべての認証器が格納されているキーを更新することができるようにします。これは、ユーザーが認証に成功するたびに呼び出されます。この API は、ユーザーの資格情報を公開することになるため、認証済みのユーザーに対してのみ呼び出す必要があります。 -
PublicKeyCredential.signalCurrentUserDetails()は、ユーザーの現在のユーザー名と表示名をブラウザーに指示するものであり、認証済みのユーザーがこれらの値を変更した際に呼び出す必要があります。この API はユーザーデータを公開するため、認証済みのユーザーに対してのみ呼び出す必要があります。
パスワードからの移行
パスキーの対応を追加するウェブサイトの多くは、すでにパスワードベースの認証に対応しており、パスワードを使用している既存のユーザー基盤を持っています。これらのユーザーは、サイト上でパスキーを所有し使用しても、アカウントに関連付けられたパスワードの所有を完全にやめるまでは、パスワードの弱点から安全とは言えません。
パスワードからのユーザー移行を実装するには、以下の 3 つの段階で行うことができます。
パスワードと併せてパスキーを生成する
まず最初に、ユーザーがパスワードでサイトへのログインに成功した際に、パスキーを生成できるオプションを提示します。
条件付き作成
パスキーの普及を促進するためのさらなる段階として、条件付き作成と呼ばれる機能があります。これにより、特定の条件が満たされた場合、RP はユーザーによる操作を一切要求せずに、ユーザーのアカウントに対して新しいパスキーを作成することができます。
条件付き作成をすることができるには、RP は CredentialsContainer.create() を呼び出し、mediation オプションを "conditional" に設定して渡します。
try {
const publicKeyCredential = await navigator.credentials.create({
publicKey: options,
mediation: "conditional",
});
// 新しいパスキー作成の処理
// ユーザーにパスキーができたことを知らせる
} catch (e) {
// パスキーが作成されなかった
}
このオプションの場合は次のようになります。
-
ユーザーがパスワードでログインした直後であれば、パスキーも対応しているパスワードマネージャー(つまり、認証器としても機能する認証情報マネージャー)を使用している場合、ブラウザーはユーザーに確認することなく、その認証情報マネージャーに対して、ユーザー用の新しいパスキーを生成するよう依頼します。
-
それ以外の場合、
create()の呼び出しは失敗します。
ユーザーの立場からすると、作成に失敗した場合、それが行われたことには気づきません。一方、成功した場合は、RP は次回ログインの際に使用できるパスキーが発行されたことをユーザーに通知することができます。
ここでの考え方は、ユーザーがすでにログインに資格情報マネージャーを利用しており、一般的に、そのマネージャーが自分のログイン資格情報を管理することを暗黙のうちに信頼しているならば、新しい形式の資格情報を作成することについても、そのマネージャーを信頼できるということです。
パスワードとパスキーの併用
ユーザーがパスワードと 1 つ以上のパスキーの両方を持っている場合、どの方法を使ってログインするかを選択できますが、リソースプロバイダー (RP) はパスキーの使用を推奨したい場合があります。
移行期間中は、ユーザーがアカウントに対してパスワードのみ、パスキーのみ、あるいはその両方を保有している可能性があります。このような状況では、どの方法でログインするか尋ねる UI は混乱を招く恐れがあります。ユーザーは、どのアカウントにどの方法があるかを覚えていない可能性があるからです。
自動入力 UI
このような状況にあるユーザーを手助けする手法の一つに、「自動入力 UI」があります。これは「条件付き仲介」と呼ばれることもあります。
この手法では、RP のログインページにフォームを表示し、ユーザーはユーザー名とパスワードを入力してログインすることができます。ユーザー名入力欄には、RP が "webauthn" という自動補完値を追加します。
<input type="text" name="username" autocomplete="username webauthn" autofocus />
バックグラウンドでは、RP がパスキーで署名されたアサーションを要求する通常のプロセスが始まります。サーバーからチャレンジを取得し、CredentialsContainer.get() に渡すその他のオプションを準備します。
ただし、RP が get() を呼び出す際、mediation: "conditional" オプションを渡します(条件付き作成の場合と同様)。
const assertion = await navigator.credentials.get({
publicKey: options,
mediation: "conditional",
});
これにより、ユーザーがユーザー名フィールドに入力を行うまで、この呼び出しは待機状態となります。ユーザーがフィールドに入力を行うと、ブラウザーは RP へのログインに使用できるパスキーを検索し、それらを自動入力値としてユーザーに表示させます。ユーザーがパスキーを選択すると、選択されたパスキーが使用され、RP はその結果として得られるアサーションを使用してユーザーのログインを完了させることができます。
ユーザーがそのサイトのパスキーを持っていない場合、または提示されたパスキーのいずれかを選択しない場合は、ユーザー名とパスワードを入力するか、パスワードマネージャーによる自動入力を利用することができます。
つまり、特別な UI を用意することなく、またユーザーが実際にそのサイトのパスキーを保有しているかどうかを覚えておく必要もなく、パスワードやパスキー、あるいはその両方を持つことができるユーザーに対応することが可能です。
パスワードの廃止
ユーザーがサイトのパスキーを保有し、パスワードの代わりにそれを使用したとしても、資格情報流用、推測、フィッシングといった攻撃に対しては脆弱な状態のままです。
そこで、最後の段階として、ユーザーにパスワードを完全に削除してもらうことを検討してもよいでしょう。これをアカウント設定のオプションとして提供し、長期間パスワードを使用していない(ただし、パスキーは定期的に使用している)ユーザーに対しては、パスワードの削除を促すことも考えられます。
ただし、パスワードを保有することで、パスキーへのアクセスを失った場合でも、ユーザーがアカウントから締め出されるのを防ぐことができるという点も同時に考えてみる必要があります。ユーザーにパスワードの削除を勧める前に、異なる認証器に複数のパスキーを設定していることや、バックアップ済みのパスキーがあるかどうかなど、代替の保護手段が整っているかを調べるとともに、確認してください。
関連情報
- ウェブ認証 API
- Passkey Central
- passkeys.dev
- パスキー (developers.google.com)