プロンプトとスコープ
プロダクト側は、サーバー側の状態(state)を削減するために、暗号化された小さな設定データをユーザーの WebAuthn 認証情報に紐付けたいと考えています。largeBlob が適するユースケース、登録と認証の違い、クライアントによる結果の確認方法、そして非対応デバイスにおいてログインとデータの正確性をどのように担保するかを説明してください。
面接官が見ているポイント
- largeBlob が一般的なクライアント側ストレージではなく、1つの認証情報に関連付けられた不透明(opaque)なデータであることを理解しているか。
- 登録時の
supportと、認証時のreadおよびwriteの入力・出力を区別できているか。 - Authenticator の容量制限、discoverable credentials、および書き込み時の「1認証情報制限」を考慮しているか。
- 機能検出(capability detection)、サーバーバックアップ、プライバシー、および失敗時のフォールバックを設計できているか。
明確にすべき質問
- データはこの認証情報とともに移動する必要がありますか?それともサーバーデータベースや IndexedDB で十分ですか?
- サイズ、機密性、復元性、およびクロスデバイスの要件はどのようなものですか?
- 対象の Authenticator は largeBlob をサポートしており、認証情報は discoverable ですか?
- 書き込みの失敗、認証情報の紛失、またはデバイスの変更後、システムはどのように復旧しますか?
30秒での回答
私なら largeBlob をプライマリストレージではなく、Authenticator のオプショナルな機能として扱います。登録時には support: preferred を要求して supported を検証し、認証時には read または write のいずれかを使用し、書き込み対象として正確に1つの認証情報を指定した上で blob または written を確認します。データは暗号化してサイズを制限し、サーバー側にも復旧可能なコピーを保持します。機能非対応、容量不足、あるいは書き込みの失敗が発生した場合は、ログインをブロックしたり未確認の書き込みを成功とみなしたりすることなく、サーバー側の状態へフォールバックします。
ステップごとの設計
1. 適切なデータ境界の選択
仕様上、largeBlob は認証情報に関連付けられた不透明なデータとして定義されています。これは認証情報に紐付く小さな設定や鍵情報には適していますが、ユーザープロファイル、複数認証情報間の同期、オブジェクトデータベースには適していません。Authenticator の容量には制限があるため、サーバー側で復旧情報を保持しておく必要があります。
2. 登録は機能検出のみに使用する
登録用拡張機能は largeBlob: { support: "preferred" } または required を受け入れます。supported は作成された認証情報が blob を保存できるかどうかを示し、登録時には blob の書き込みは行われません。required を使用すると非対応の Authenticator は除外されるため、必須にする前に互換性への影響を測定してください。
3. 認証時の読み出しと書き込みの分離
認証では read: true を要求するか、write を提供するかのいずれかが可能です(両方を同時に指定すると失敗します)。書き込みを行うには allowCredentials に正確に1つの認証情報が含まれている必要があり、成功は written によって通知されます。blob メンバーは、単に拡張オブジェクトが存在するからではなく、読み出しが成功した後にのみ存在します。
4. プライバシー、復旧、フォールバックの設計
Authenticator 内のデータは不透明(opaque)であり、アプリケーション層で自動的に暗号化されるわけではありません。クライアントとサーバー側で暗号化、バージョニング、整合性チェックを実装する必要があります。認証情報が利用できない、デバイスが非対応である、容量が不足している、またはユーザーが拒否した場合は、サーバー側のコピーを使用します。機能の可否や結果はログに記録しますが、blob の中身は決して記録しないでください。
模範解答
私は largeBlob をサーバー側の状態の完全な代替として使用することはしません。これは単一の WebAuthn 認証情報に小さな不透明な値を紐付ける用途に有用です。登録時には support: preferred を要求して supported を検証し、認証時には read または write を選択し、1つの認証情報を書き込み対象として指定した上で blob または written を確認します。アプリケーションが暗号化、バージョニング、整合性を担い、サーバーは復旧可能なコピーを保持します。非対応の Authenticator、discoverable credential の制約、容量エラー、書き込み失敗、デバイス変更などはすべて、認証を妨げることなくサーバー側の状態にフォールバックします。この機能を必須とするのは、プロダクト側で互換性の低下が許容され、移行計画が整っている場合に限定します。これにより、ログインや復旧を過度に依存させることなく、Authenticator のストレージを活用できます。
よくある間違い
- largeBlob を IndexedDB や Cookie、あるいは無制限にクラウド同期されるストレージのように扱うこと。
- 登録時に blob を書き込めると思い込むこと。
readとwriteを同時に指定したり、書き込み対象として複数の認証情報を指定したりすること。supported、blob、またはwrittenを検証せず、単に拡張オブジェクトが存在することだけを確認すること。- アプリケーションによる暗号化を行わずに、不透明な blob に機密データを書き込むこと。
- Authenticator が非対応の場合にサーバーへフォールバックせず、ログインをブロックしてしまうこと。
フォローアップ質問と回答
preferred と required はどのように選択しますか?
preferred は非対応の Authenticator を許容してフォールバックを可能にしますが、required はそれを除外します。プロダクトが互換性の低下を許容し、その機能に完全に依存している場合を除き、preferred を優先すべきです。
なぜ書き込みは正確に1つの認証情報を対象にする必要があるのですか?
仕様上、更新対象の認証情報を特定するために単一の allowCredentials ターゲットを使用します。複数の候補が存在すると「非サポート操作」のエラーが発生するため、アプリケーションは事前にユーザーの認証情報を特定しておく必要があります。
デバイス移行の計画はどのようになりますか?
blob はオプショナルなキャッシュまたは鍵のコピーとして扱い、復旧用データはサーバー側に保持します。新しいデバイスは再登録または認証を通じてサーバーの状態を取得します。Authenticator の blob がデバイス間で同期されるとは想定しないでください。