パスワードは数十年にわたってWeb認証の主要な仕組みでしたが、セキュリティとユーザビリティに多くの問題を抱えています。WebAuthn(Web Authentication)とパスキーエコシステムは、暗号学的に安全でフィッシング耐性のある認証を実現します。2024年現在、主要プラットフォームすべてがパスキーをサポートしており、パスワードレス認証を導入する絶好のタイミングです。
WebAuthnの理解
WebAuthnは公開鍵暗号ベースの認証を実現するW3C標準です。登録フローでは、サーバーが暗号学的チャレンジを送信し、認証機が鍵ペアを生成、公開鍵がサーバーに保存されます。認証フローでは、サーバーがチャレンジを送信し、認証機が秘密鍵で署名、サーバーが公開鍵で署名を検証します。
登録: サーバー → チャレンジ → 認証機(鍵ペア生成) → 公開鍵 → サーバー
認証: サーバー → チャレンジ → 認証機(秘密鍵で署名) → 署名 → サーバー(検証)
秘密鍵は認証機から外部に出ないため、フィッシング、クレデンシャルスタッフィング、サーバーサイドのデータベース侵害に対して本質的に耐性があります。
パスキーの概念
パスキーは発見可能なWebAuthn認証情報であり、ユーザーのデバイスに安全に保存され、iCloudキーチェーンやGoogleパスワードマネージャーなどの仕組みを通じてデバイス間で同期されます。パスキーはユーザーがサイトごとに管理でき、生体認証またはPINで保護され、QRコードによるクロスデバイス認証も可能です。従来の認証情報とは異なり、パスキーはエンドユーザーが直接管理できるように設計されています。
プラットフォーム認証機 vs ローミング認証機
プラットフォーム認証機はデバイスに内蔵されています(Touch ID、Windows Hello、Android生体認証)。ローミング認証機はUSB、NFC、Bluetooth経由で接続する外部セキュリティキー(YubiKey、Titan Key)です。セキュリティ要件とユーザーエクスペリエンスに基づいて選択します。
| 特徴 | プラットフォーム認証機 | ローミング認証機 |
|---|---|---|
| 入手性 | デバイス内蔵 | 別途購入が必要 |
| 携帯性 | エコシステム内で同期 | 物理的に携帯可能 |
| セキュリティ | 良好 | 非常に高い(ハードウェア) |
| UX | シームレス(生体認証) | キーの挿入が必要 |
| クロスデバイス | クラウド同期 | 手動転送 |
条件付きUI
条件付きUIは、ログインフローでブラウザがパスキーの自動入力を提案できるようにします。ユーザーは保存済みパスワードと並んでパスキーオプションを自動入力ドロップダウンに表示され、変換率が大幅に向上します。
const credential = await navigator.credentials.get({
publicKey: publicKeyCredentialRequestOptions,
mediation: "conditional",
});
実装には3つの手順が必要です。mediation: "conditional"の設定、入力フィールドへのautocomplete="username webauthn"の追加、およびautofill処理の適切な実装です。この機能により、ユーザーが既に理解している自動入力エクスペリエンスにパスキー認証が統合されます。
JavaScriptによる実装
以下のコードは、WebAuthnの登録および認証フローの基本を示しています。
// 登録
const publicKeyCredential = await navigator.credentials.create({
publicKey: {
challenge: crypto.getRandomValues(new Uint8Array(32)),
rp: { name: "My App", id: "example.com" },
user: {
id: crypto.getRandomValues(new Uint8Array(16)),
name: "[email protected]",
displayName: "User",
},
pubKeyCredParams: [{ alg: -7, type: "public-key" }],
authenticatorSelection: {
residentKey: "preferred",
userVerification: "preferred",
},
},
});
// 認証
const assertion = await navigator.credentials.get({
publicKey: {
challenge: crypto.getRandomValues(new Uint8Array(32)),
allowCredentials: credentials.map(cred => ({
id: base64urlToBytes(cred.id),
type: "public-key",
})),
userVerification: "preferred",
},
});
サーバーサイドの検証では、attestationオブジェクトの解析、暗号署名の検証、オリジンとRP IDの一致確認が必要です。Node.js向けの@simplewebauthn/serverなどのライブラリを使用すると、この処理を大幅に簡略化できます。
セキュリティの考慮事項
WebAuthnはフィッシング、クレデンシャルスタッフィング、中間者攻撃、データベース侵害などの攻撃カテゴリ全体を排除します。ただし、適切な実装が不可欠です。オリジンがRP IDと一致することを確認し、暗号学的にランダムな使い捨てチャレンジを生成し、認証試行のレート制限を実装し、デバイス紛失時の復旧オプションを提供してください。移行期間中はパスワードフォールバックを維持し、パスワードログイン成功後の段階的パスキー登録(プログレッシブエンロールメント)を通じてユーザーの移行を促進します。
結論
パスキーは10年ぶりのWeb認証セキュリティの最も重要な改善です。主要プラットフォームがエコシステムをサポートし、ユーザーが生体認証にますます慣れている中、2024年はパスキーを採用する年です。実装の複雑さは中程度で、セキュリティとユーザーエクスペリエンスの利点は非常に大きいです。パスワードを排除することで、攻撃ベクター全体を排除しながら、よりスムーズな認証体験をユーザーに提供できます。
