spinny:~/writing $ less passkeys-webauthn-passwordless-authentication.md
12パスワードは、私たちが何年もパスワードと付き合ってきたという理由だけで標準化したものの 1 つです。ユーザーはそれらを忘れたり、再利用したり、書いてはいけない場所に書いたりします。チームは、リセット、ポリシー、ハッシュ、リーク、フィッシング、サポートを管理する必要があります。34passkey によって認証が完璧になるわけではありませんが、サーバーはユーザーと共有する秘密を保持する必要がなくなるという大きな問題が解決されます。56## 実際に何が起こるか78passkey は、WebAuthn に基づく資格情報です。ユーザーがキー ペアを作成すると、デバイスはキー ペアを生成します。910- 秘密キー。デバイスまたはパスワード マネージャーに残ります。11- サーバーが保存できる公開キー。1213サーバーにログインするときに、「パスワードを教えてください」と尋ねられることはありません。ランダムなチャレンジを送信します。デバイスは秘密キーを使用して署名します。サーバーは公開キーを使用して署名を検証します。1415これは良い点です。データベースが盗まれても、内部に解読できるパスワードはありません。また、ユーザーが偽のドメインを使用することになった場合、そのドメインでは passkey は無効になります。これは単なる利便性ではなく、フィッシングに対する具体的な保護でもあります。1617## ブラウザはブリッジとして機能します1819ブラウザでは、主な 2 つの API は次のとおりです。2021- `navigator.credentials.create()` で passkey を作成します。22- `navigator.credentials.get()` ログイン時に使用します。2324ただし、重要なロジックはサーバー上にあります。サーバーはチャレンジを生成し、一時的に保存し、応答を検証し、ソースと Relying Party ID を確認してから、セッションを作成する必要があります。2526クライアント部分はほとんど退屈なものになるはずです。2728```typescript29const options = await fetch('/api/passkeys/login/options').then((r) => r.json());3031const credential = await navigator.credentials.get({32 publicKey: PublicKeyCredential.parseRequestOptionsFromJSON(options),33});3435await fetch('/api/passkeys/login/verify', {36 method: 'POST',37 headers: { 'Content-Type': 'application/json' },38 body: JSON.stringify(credential?.toJSON()),39});40```4142WebAuthn 暗号化を手動で実装していることに気付いた場合は、やめてください。堅牢なサーバー側ライブラリを使用します。ここでのエラーは「かわいいバグ」ではなく、認証ホールです。4344## データベースに何を保存するか4546世界の半分を救う必要はない。通常は十分です:4748- 資格情報の ID。49- 公開鍵。50- 接続されているユーザー。51- 検証カウンターまたはメタデータ。52- トランスポート (UX に役立つ場合)。53- ユーザーが選択した名前。54- 作成日と最終使用。5556最小限のテーブルは次のようになります。5758```sql59create table passkey_credentials (60 id uuid primary key default gen_random_uuid(),61 user_id uuid not null references users(id),62 credential_id text not null unique,63 public_key text not null,64 name text,65 created_at timestamptz not null default now(),66 last_used_at timestamptz67);68```6970次に、監査ログと通知を追加します。誰かが私のアカウントに新しい passkey を作成した場合、それについて知りたいと思います。7172## デモよりも UX が重要7374passkey のデモは常に美しく、Face ID をクリックすれば完了です。実際の製品はさらに複雑です。7576誰かが携帯電話を変更します。誰かがロックされた会社のコンピューターを使用しています。なぜブラウザが passkey を提案するのか理解できない人もいます。誰かが自分のデバイスにアクセスできなくなりました。7778これが、私が「今日から全員のパスワードを廃止する」ということから始めない理由です。私なら次のように始めます。79801. passkey 内部ユーザーの場合はオプションです。812. ログインに成功した後に作成するよう提案します。823. アカウントページの名前を変更して削除します passkey;834. フォールバックをクリアする。845. メインログインでの段階的なロールアウト。8586インターフェース内のテキストはシンプルである必要があります。 「デバイスのロック画面を使用する」は、「常駐の FIDO2 資格情報で認証する」よりも優れています。8788## 避けたい間違い8990クライアントでチャレンジを生成しないでください。チャレンジはサーバー上で作成され、検証する必要があるのは 1 回だけです。9192認証情報 ID だけを信頼しないでください。署名、チャレンジ、出所、および Relying Party ID を検証する必要があります。9394適切なリカバリ フローを確立する前に、フォールバックを削除しないでください。パスワードレス化しても、「携帯電話を紛失したら永久に使えなくなる」という状況になる必要はありません。9596passkey を純粋にフロントエンド ボタンとして扱わないでください。ボタンを非表示にすることはセキュリティではありません。実際の検証はサーバー側で行われます。9798## Passkey 優先ですか、それとも passkey 優先ですか?99100新しい製品については、passkey-を最初に考えることができます。既存のアプリの場合、私は passkey フレンドリーを好みます。推奨される方法として passkey を追加し、成功と問題を測定してから、冷静にパスワードの重みを減らします。101102理想的な移行は感じられません。ユーザーは、会社が認証プロトコルを変更したことではなく、ログインが簡単になったことに気づきました。103104## 結論105106passkey は、セキュリティと UX を同時に向上させるという珍しい点で興味深いです。これらは魔法の杖ではありません。回復、互換性、サポート、展開は適切に設計される必要があります。107108しかし、基本的な変化は強力です。ユーザーに秘密を発明して保護するよう求めるのはやめましょう。デバイスに、ドメインに関連付けられた暗号化証明に署名させます。人間の記憶力が減り、フィッシングも減り、パスワードのリセットも減ります。真剣に受け止める価値があると思います。109110## ソース111112- [MDN: Passkeys](https://developer.mozilla.org/en-US/docs/Web/Security/Authentication/Passkeys)113- [MDN: Web Authentication API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API)114- [W3C: Web Authentication](https://www.w3.org/TR/webauthn-3/)115- [passkeys.dev](https://passkeys.dev/)116
:Passkey および WebAuthn: パスワードなし、魔法なしでログインします。lines 1-116 (END) — press q to close