パスキーってなに
FIDOとは
普及に課題があったFIDO
- FIDO(Fast IDentity Online Alliance)は生体情報などを利用した新しいオンライン技術の標準化を目指して2012年7月に発足した非営利の標準化団体、業界団体。
- FIDOがUAF(Universal Authentication Framework)とU2F(Universal 2nd Factor)を公開
- FIDOでは専用の認証機を使用する必要があること、対応ブラウザが少ないといった理由から、普及には課題があった
FIDO2
- 2018年9月にFIDO2を公開
- いつも使っているスマホの機能を利用することで、利用者にストレスを与えずにパスワードレスを実現できるように
- FIDOでは専用機を使うため、生体の精度が悪いという問題が指摘されていたが、Apple TouchID/FaceID、Android、Windows Helloの精度は、高い・低いというレベルではなく、「いつも使っている」機能として無意識に利用しているので、「精度が悪い」という問題にはなっていない
- FIDO2 = WebAuthnではなく、2つの要素で構成されている
WebAuthnの課題
- 端末内に認証資格情報を保管するので、その端末でしか使えない
- つまり、機種変更、紛失時に、新しい端末で改めてログイン設定が必要になる
- この課題を解決するのがPasskeysである
パスキーの概要
- WebAuthnの課題を解決するために、認証資格情報を複数の端末で同期できる仕組みが「Passkeys」として規格化された
- 例えば、Microsoftアカウント、Apple ID、Googleアカウントなどの対応サービスを使うことで、同じアカウントを登録した端末間で認証資格情報を同期できるように
- 同じApple IDを登録したMacとiPhone、iPadの各端末で生体認証を使い、それぞれの端末だけでFIDO2認証を使ったログインが可能になったのです。
- AppleでPasskeysを利用するには、2段階認証が設定されている必要がある
パスキーの特性
- ユーザーは PIN コードまたは生体認証を使用してデバイスで認証できます。秘密鍵はユーザーのデバイスに保存され、公開鍵はアプリケーションに保存される
- パスキーはユーザーのデバイス (複数可) にバインドされており、ブルート フォース攻撃は不可能であるため、潜在的な攻撃者はデバイスに物理的にアクセスする必要がある
- パスキーはユーザーの身元を確認する認証情報であるが、ユーザーがデバイスにアクセスできるかどうか (ユーザー プレゼンス) を確認できます。これにより、WebAuthn は通常のパスワードに加えて、優れた第 2 要素として使用できます。ここでは、PIN コードや生体認証を提供しないハードウェア セキュリティ トークンを使用できます。
- 発行者はOSである (android,ios,chrome)
- AndroidやChromeなどそれぞれ異なる場所でパスキーが作られており、それらは共有されない
- しかし、QRコードを用いてコードを読み取ることで認証することもできる
Relying Party(RP)
- 開発者が開発するアプリケーションを指す
- パスキーではRPのドメイン情報を証明書に含める
ウェブ認証 API
- 登録手順中に、認証者は新しい資格情報を作成し、その公開鍵を返す
- クライアントでは、サーバーから新しいチャレンジを取得し、Web 認証 APIを使用して新しい資格情報を作成する。
- これにより、ユーザーはデバイスで認証するように求められます。Safari などのブラウザでは、ユーザー操作 (ボタンのクリック) によって開始された場合にのみ、このメソッドを呼び出すことができます。
認証フロー
認証情報を取得する
公開鍵の認証情報を作るために、サーバーからユーザー情報、既に登録済みのパスキーの公開鍵認証情報などを取得する
必要な情報 | 説明 |
---|---|
RP ID | Relying party を識別するID。ドメインを指定する。 |
チャレンジ | Relying party(サービス)が発行するリプレイ攻撃防止のためのランダム生成文字列。 |
user id | ユーザーの認証ID。ユーザーのクレデンシャルを紐付けるユニークな値。64バイトのID。 |
user name | 人間が識別し易いユーザーの識別名。例えばメールアドレスなどを指定する。ID/PasswordがあればそのIDを使う。ユーザーに対して一意である必要がある |
user display name | ユーザーが認識し易い名前。ユーザーが決めた名前でよくユニークである必要もない。Relying party(サービス)がこれを持たない場合は空白で良い。 |
excludeCredentials | 同じID(同じデバイス)でクレデンシャルを登録されることを防ぐために、既に存在するIDのリストをサーバーから |
excludeCredentialsに含まれる情報 |
情報 | 説明 |
---|---|
id | 公開鍵クレデンシャルのID |
type | 公開鍵クレデンシャルの種類 |
transports | 公開鍵がどのような認証方法で登録されたかのヒント情報 |
パスキーの作成
サーバーから受け取った情報を元に WebAuthn APIを使ってパスキーを作成します。 https://developer.mozilla.org/ja/docs/Web/API/CredentialsContainer/create
パスキーを作成するには、WebAuthn APIの navigator.credentials.create
というAPIを利用します。
このAPIを使うことで まずブラウザ経由で、OSやその他認証器による認証処理が行われパスキーが作成されます。
chromeで
navigator.credentials.create
を実行したときのダイアログ
全て完了すると、パスキーの公開鍵認証情報がJavaScriptから受け取れます。
公開鍵認証情報をサーバーへ送信
作成されたパスキーの公開鍵認証情報をサーバーへ送信します。
サーバーでは、チャレンジや認証情報が問題ないかの検証を行います。
パスキーの公開鍵認証情報(PublicKeyCredential)には以下のような値が含まれています。
情報 | 説明 |
---|---|
rawId | クレデンシャルのグローバルな固有識別子。 |
id | rawIdをbase64で符号化した識別子。 |
response.clientDataJSON | クライアントの認証情報。JSON互換。 |
response.attestationObject | 公開鍵を含む重要情報。 |
https://developer.mozilla.org/ja/docs/Web/API/PublicKeyCredential
パスキーの公開鍵認証情報をデータベースへ保存
最後に公開鍵認証情報のID、ユーザーID、公開鍵などを、管理するデータベースに保存します。
今後はこの情報を元にユーザーの認証を行います。
認証情報の検証を含む処理は、セキュリティリスクもあるため、安定したサードパーティのライブラリを使うことも検討すると良いようです。 https://github.com/herrjemand/awesome-webauthn#server-libraries
認証フロー
保存したパスキーの情報でユーザーが実際にパスキーを使用して、サービスの認証を行うフローです。 https://w3c.github.io/webauthn/#sctn-api
認証の主な流れとして、ユーザーがパスキーを使用して、ログイン処理を行う場合は「デバイスから作成済みのパスキーを取得する」必要があります。
これは、WebAuthn API の navigator.credentials.get()
というAPIが用意されています。
https://developer.mozilla.org/ja/docs/Web/API/Navigator/credentials
パスキーが利用可能か判断する
PublicKeyCredential
isUserVerifyingPlatformAuthenticatorAvailable() static method
ユーザー検証プラットフォーム認証子は、クライアント デバイスの一部 (通常は取り外し不可) であり、ユーザーを識別するためにユーザーのアクションを必要とする多要素認証子の一種です。一般的なユーザー検証プラットフォーム認証子には、次のものがあります。
- Touch ID または Face ID (macOS および iOS)
- Windows Hello (Windows)
- Android でのデバイスのロック解除 (指紋、顔、PIN など)
戻り値
ユーザー検証プラットフォーム認証が利用可能かどうかを示すブール値に解決するPromise。
isConditionalMediationAvailable static method
ユーザーが条件付きのユーザー認証を利用可能かどうかを判定する。Conditional Mediationはモーダル UI をトリガーせずにウェブサイトで WebAuthn リクエストを行うことを許可するもの。つまり、ユーザーがユーザー名入力フィールドをタップすると、自動入力の候補が表示され、保存されたパスキーやパスワードから選択できるようになります。
https://developer.chrome.com/docs/identity/webauthn-conditional-ui?hl=ja
多要素認証ではだめなのか
- スミッシングに引っかかって
- フィッシングサイトにアクセスし、ID/パスワードの他、ワンタイムパスワードも入力してしまい
- それらが脅威アクターに転送され
- 転送された情報を使ってIDPサイト(正規サイト)にログインする
Reference
- https://developer.mozilla.org/ja/docs/Web/API/Web_Authentication_API
- https://thecopenhagenbook.com/passkeys
- https://www.lac.co.jp/lacwatch/service/20230525_003389.html
- https://zenn.dev/hakoten/books/c9718954916f82/viewer/8d31c6
- https://developers.google.com/identity/passkeys/use-cases?hl=ja#sign-in-with-a-phone
- https://w3c.github.io/webauthn/#sctn-intro