
Passkeys / WebAuthn 入門 - パスワードレス認証を管理画面に入れる前に知っておくこと
パスワードは、使い回し・漏洩・フィッシングと、弱点だらけの認証方式です。その置き換えとして実用段階に入ったのがパスキー(Passkeys)、その土台が Web Authentication API(WebAuthn)です。
この記事では、パスキー / WebAuthn の仕組みを公開鍵暗号の観点から整理し、「自分のサービスの管理画面に入れるべきか」を判断するための材料(フィッシング耐性・復旧手段・MFAとの違い)までをまとめます。
パスキーとは何か
パスキーは、パスワードの代わりに公開鍵暗号で認証する仕組みです。WebAuthn を使って実装されます。
仕組みの核はシンプルです。
- 登録時に、デバイス(認証器)が鍵ペア(秘密鍵・公開鍵)を生成する
- 秘密鍵はデバイスから出ない。サーバには公開鍵だけを保存する
- 認証時は、サーバが送った「チャレンジ」に秘密鍵で署名し、サーバが公開鍵で検証する
パスワードのように「共有の秘密」をサーバに預けないのが本質的な違いです。サーバが漏洩しても、保存されているのは公開鍵だけなので、攻撃者はなりすませません。
なぜパスワードより安全なのか
サーバ漏洩に強い
サーバが持つのは公開鍵のみ。公開鍵が漏れても、それだけでは認証できません。パスワードハッシュの流出とは状況が根本的に違います。
フィッシングに強い(これが最大の利点)
パスキーの署名はオリジン(ドメイン)に紐づきます。偽サイト acme-phishing.com でログインを促されても、認証器は「期待される RP(Relying Party)のオリジンと違う」と判断して署名を拒否します。
1. 攻撃者が偽サイト acme-phishing.com を用意
2. ユーザーが気づかず認証しようとする
3. 認証器が期待オリジン(acme.com)と照合
4. 不一致 → 署名を拒否 → 認証失敗「うっかり偽サイトで認証してしまう」が原理的に起きにくい。パスワードや SMS ワンタイムコードでは防げないフィッシングを、仕組みで止められるのが決定的な強みです。これは TanStack/TeamPCP 事件のような認証情報窃取が横行する時代に効いてきます。
仕組み: 登録と認証の2つのセレモニー
WebAuthn の操作は「登録」と「認証」の2段階です。
登録(navigator.credentials.create)
const credential = await navigator.credentials.create({
publicKey: {
challenge, // サーバが生成した乱数(16バイト以上)
rp: { id: 'acme.com', name: 'ACME' },
user: { id, name: 'jamie', displayName: 'Jamie Doe' },
pubKeyCredParams: [{ type: 'public-key', alg: -7 }],
},
})
// 生成された公開鍵をサーバへ送り、検証して保存認証器が鍵ペアを生成し、公開鍵をサーバに登録します。
認証(navigator.credentials.get)
const credential = await navigator.credentials.get({
publicKey: {
challenge, // サーバが毎回生成する乱数
rpId: 'acme.com',
userVerification: 'required',
},
})
// 署名をサーバへ送り、保存済み公開鍵で検証認証器が秘密鍵でチャレンジに署名し、サーバが公開鍵で検証します。秘密鍵そのものは決して送られません。
認証器の種類と「同期パスキー」
| 種類 | 例 |
|---|---|
| プラットフォーム認証器 | Windows Hello、Touch ID/Face ID など OS 内蔵 |
| ローミング認証器 | USB/Bluetooth のセキュリティキー(YubiKey 等) |
| 同期パスキー | iCloud キーチェーン、Google パスワードマネージャ等でデバイス間同期 |
実用上の主役は同期パスキーです。iCloud や Google アカウントを通じて複数デバイスにパスキーが同期されるため、「機種変更したらログインできない」を避けられます。なお、パスキーは仕様上discoverable credential(保存型)である必要があり、これによりユーザー名を先に入力しなくてもログインできる(autofill UI)利点が生まれます。
管理画面に入れるときの判断材料
「自分のサービスに入れるべきか」を考えるときのチェックポイントです。
復旧手段を必ず設計する
パスキーの最大の運用課題はアカウント復旧です。デバイスを失ったときどうするか。同期パスキーである程度は緩和されますが、
- 複数の認証器を登録できるようにする(予備デバイス・セキュリティキー)
- メール等のバックアップ経路を用意する
- 「全パスキーを失った場合」のサポートフローを決めておく
を設計しないと、ユーザーを締め出してしまいます。
MFA との違いを理解する
パスキーは「2要素のうちの1つ」ではなく、それ単体でフィッシング耐性のある認証になり得ます(生体認証+デバイス所持で実質多要素)。「パスワード+SMS」を「パスワード+パスキー」に足すのではなく、パスワードレスの主役として設計するのが本筋です。
段階的導入が現実的
いきなりパスワード全廃は難しいので、
- まず「パスキーも使える」オプションとして追加(パスワードと併存)
- autofill UI(
autocomplete="username webauthn")で自然に促す - 普及を見て、パスワードレスを既定にしていく
という段階導入が現実的です。
WARNING
WebAuthn はセキュアコンテキスト(HTTPS)必須です。また RP ID(ドメイン)の設計を最初に誤ると後で移行が大変になります。サブドメイン構成やドメイン変更の可能性を踏まえて RP ID を決めてください。
まとめ
- パスキーは公開鍵暗号でパスワードを置き換える方式。秘密鍵はデバイスから出ず、サーバは公開鍵のみ保持
- 最大の強みはフィッシング耐性。署名がオリジンに紐づくため、偽サイトでは認証器が署名を拒否する
- 操作は登録(
navigator.credentials.create)と認証(navigator.credentials.get)の2セレモニー - 実用の主役は同期パスキー(iCloud/Google 同期)。仕様上 discoverable credential が必要
- 導入判断の肝は「復旧手段の設計」と「MFAの足し算ではなくパスワードレスの主役として設計」
- HTTPS 必須、RP ID(ドメイン)設計は最初に慎重に
パスワードの諸問題を、運用でなく仕組みで解決できるのがパスキーの価値です。まずは「パスキーも使える」オプションとして管理画面に足すところから、段階的に始めるのがおすすめです。