FIDO2に重要なWeb Authenticationの仕様の7章Relying Partyについて書かれている部分を邦訳した。
(表記ゆれは残っているし、誤訳もあるかも。。。)
この内容をもとにYahoo! JAPANでの生体認証の取り組み(FIDO2サーバーの仕組みについて) - Yahoo! JAPAN Tech Blogでは実装されているはずなので、参考にしてFIDOについて勉強していく予定。
FIDO2やWen Authenticationの基本的な内容は、以下の記事などを参照。
登録処理または認証処理は、WebAuthn Relying PartyがそれぞれPublicKeyCredentialCreationOptions
オブジェクトまたはPublicKeyCredentialRequestOptions
オブジェクトという処理に使用するパラメータをエンコードしたオブジェクトを作成することから始まります。Relying Partyはこの段階で機密情報を漏らさないように注意しなければなりません(SHOULD)。詳細は§ 14.6.2 Username Enumerationを参照してください。
create()
またはget()
の実行に成功した場合、Relying Partyのスクリプトは、クライアントからそれぞれAuthenticatorAttestationResponse
構造またはAuthenticatorAssertionResponse
構造を含んだPublicKeyCredential
を受け取ります。本仕様外のメソッドによって、この構造のコンテンツはRelying Partyのサーバに届けられなければなりません。このセクションではRelying Partyが受け取ったこれらの構造のオブジェクトに対しておこなう処理について記述しています。
登録処理を実行するため、Relying Partyは以下のことを実施しなければなりません(MUST):
PublicKeyCredentialCreationOptions
構造に設定する。navigator.credentials.create()
を呼び出し、publicKey
オプションとして option を受け渡す。Promiseが正常にresolveされた結果を credintial とする。Promiseがrejectされた場合、ユーザが見ることができるエラーによって処理を中止する、もしくはrejectされたPromiseから取得できる情報から判定できるユーザ操作に導く。例えば、「InvalidStateError
」と同等なエラーコードによってPromiseがrejectされた場合、別の認証器を利用するようにユーザに指示する。その他エラーおよび環境での情報は、§ 6.3.2 The authenticatorMakeCredential Operationを参照。注意:UTF-8デコードの他の実装を利用することは、UTF-8デコードアルゴリズムと同じ結果を出力するかぎり認められています。特に先頭のバイト順マーク(BOM)は取り除かなければなりません(MUST)。
注意: C はこのアルゴリズムが必要なときに C のコンポーネントを参照可能なかぎり、実装特有なデータ構造表現にして構わない。
webauthn.create
と一致することを検証する。flags
のUser Presentビットが設定されていることを検証する。flags
のUser Verifiedビットが設定されていることを検証する。alg
属性と一致することを検証する。extensions
のauthenticator extension outputsの値が期待通りであることを検証する。これは options.extensions で渡されたclient extension inputの値および未承認、つまり options.extensions 部分に記載されていないextensionsに関するRelying Party独自のポリシーについて考慮したものである。一般的に、「期待通りであること」という意味はRelying Partyとどのようなextensionsが利用されているかによって変わる。注意:クライアントプラットフォームは、追加的なauthenticator extensionsまたはclient extensionsを設定するためのローカルポリシーを規定するかもしれない(MAY)。つまり、これらは options.extensions 部分で元来定められていなかったauthenticator extension outputsまたはclient extension outputsを表現する値を必要とする。Relying Partyは未承認のextensionsを無視するかattestationを拒絶するかに関わらず、このような状態に対応できるようにしなければならない(MUST)。Relying Partyはローカルポリシーと利用されているextensionsに基づいてこの決定をおこなうことができる。
注意:クライアントと認証器の両方において全てのextensionsはOPTIONALであるため、Relying Partyは必須となるextensionsが全て実行されないケースおよび一部が実行されないケースに対応できるようにしなければならない(MUST)。
注意:それぞれの attestation statement formatは独自の検証手順を有する。初期に定義されたフォーマットについては§ 8 Defined Attestation Statement Formatsを参照し、最新のリストは[IANA-WebAuthn-Registries]を参照する。
attestedCredentialData
のaaguid
を利用してそれらの情報を取得する方法の1つである。credentialId
がどのユーザに対して登録されていないことを確認する。既に他のユーザに登録されているクレデンシャルの登録が要求された場合、Relying Partyはこの登録処理を失敗させるべきである(SHOULD)、または例えば古い登録を削除して登録を受け入れると決めることができる(MAY)。credentialId
およびcredentialPublicKey
を関連付ける。credentialId
と authData.signCount の値で初期化して新規保存したsignature counterの値を関連付ける。credentialId
と credential.response.getTransports() を呼び出した戻り値であるtransport hintsを関連付ける。この値は保存前後で変更すべきではない(SHOULD NOT)。後述のget()
の呼び出しにおいてClientが適切な認証器を見つける方法を知る手助けとなるようにallowCredentials
オプションのtransports
に情報を入れるため、この値を使うことを推奨する(RECOMMENDED)。注意:ただし、ポリシーによって許可された場合、Relying Partyはcredential IDおよび公開鍵を登録することができる(MAY)が、self attestation(§ 6.5.3 Attestation Types参照)と関連付いていることとなり、クレデンシャルを脅かすことになる。これを実施した場合、Relying Partyは特定の認証器モデルによって生成された公開鍵は暗号証明がないことを検証する。更に詳細な議論は[FIDOSecRef]および[UAFProtocol]を参照。
attestation objectsの検証は、Relying Partyが上述のステップ20においてアクセス可能なトラストアンカーを決定するための信用できる方法を有していることが必須である。また、証明書が使用された場合、Relying Partyは中間CA証明書に証明書ステータス情報にアクセスしなくてはならない(MUST)。さらに、Clientがattestation情報でattestation certificate chainについて知らせなかった場合、Relying Partyはそのチェーンを構成することができなければならない。
認証処理を実行するため、Relying Partyは以下の内容を実行する必要がある(MUST):
PublicKeyCredentialRequestOptions
構造を設定する。transports
要素は対応するクレデンシャルが登録されたときの credential.response.getTransports() の戻り値を設定するべきである(SHOULD)。navigator.credentials.get()
を呼び出し、publicKey
オプションとして options を受け渡す。 credential にPromiseのresolveが成功した結果を設定する。Promiseがrejectされた場合、ユーザが見ることができるエラーによって処理を中止する、もしくはrejectされたPromiseから取得できる情報から判定できるユーザ操作に導く。その他エラーおよび環境での情報は、§ 6.3.3 The authenticatorGetAssertion Operationを参照。AuthenticatorAssertionResponse
のインスタンスではない場合、ユーザが見ることができるエラーによって処理を中止する。認証されたユーザであることを特定し、そのユーザが credential.id で指定された公開鍵認証ソース credentialSource のオーナーであることを検証する:
認証処理を開始する前に例えばユーザ名やcookieによりユーザが特定されていた場合、
特定されたユーザが credentialSource のオーナーであることを検証する。 response.userHandle が存在する場合、 userHandle にその値を設定する。また、 userHandle が同じユーザに紐付いていることを検証する。
認証処理を開始する前にユーザが特定されていなかった場合、
response.userHandle が存在することおよびその値によって特定されたユーザが credentialSource のオーナーであることを検証する。
credential.id (または、base64urlエンコーディングが自身のユースケースに不適切な場合にはcredential.rawId)を利用して対応する公開鍵を探し出し、 credentialPublicKey に公開鍵を設定する。
clientDataJSON
、authenticatorData
およびsignature
の値を割り当てる。注意:UTF-8デコードの他の実装を利用することは、UTF-8デコードアルゴリズムと同じ結果を出力するかぎり認められています。特に先頭のバイト順マーク(BOM)は取り除かなければなりません(MUST)。
注意: C はこのアルゴリズムが必要なときに C のコンポーネントを参照可能なかぎり、実装特有なデータ構造表現にして構わない。
webauthn.get
という文字列であることを検証する。注意:appid extensionを利用する場合、このステップで特別なロジックが必要となります。詳細は§ 10.1 FIDO AppID Extension (appid)を参照。
flags
のUser Presentビットが設定されていることを検証する。flags
のUser Verifiedビットが設定されていることを検証する。extensions
のauthenticator extension outputsの値が期待通りであることを検証する。これは options.extensions で渡されたclient extension inputの値および未承認、つまり options.extensions 部分に記載されていないextensionsに関するRelying Party独自のポリシーについて考慮したものである。一般的に、「期待通りであること」という意味はRelying Partyとどのようなextensionsが利用されているかによって変わる。注意:クライアントプラットフォームは、追加的なauthenticator extensionsまたはclient extensionsを設定するためのローカルポリシーを規定するかもしれない(MAY)。つまり、これらは options.extensions 部分で元来定められていなかったauthenticator extension outputsまたはclient extension outputsを表現する値を必要とする。Relying Partyは未承認のextensionsを無視するかattestationを拒絶するかに関わらず、このような状態に対応できるようにしなければならない(MUST)。Relying Partyはローカルポリシーと利用されているextensionsに基づいてこの決定をおこなうことができる。
注意:クライアントと認証器の両方において全てのextensionsはOPTIONALであるため、Relying Partyは必須となるextensionsが全て実行されないケースおよび一部が実行されないケースに対応できるようにしなければならない(MUST)。
注意:この検証ステップはFIDO U2F認証器によって生成された署名に互換性がある。§ 6.1.2 FIDO U2F Signature Format Compatibility参照。
storedSignCount に credential.id の関連付けられて保存されたsignature counterの値を設定する。authData.signCount がゼロではない場合、もしくは storedSignCount がゼロではない場合、以下の追加ステップを実行する:
authData.signCount が、
storedSignCount より大きい場合、
authData.signCount の値に storedSignCount を更新する。
storedSignCount より小さいもしくは同じ場合、
認証器が複製されている可能性がある、つまり秘密鍵の複製が最低でも2つ存在している可能性があり、同時に利用されていることを示唆する。Relying Partyはこの情報をリスクスコアリングに組み入れるべきである。このような場合、Relying Partyは storedSignCont を更新するか更新しないか、もしくは認証処理を失敗させるか失敗させないかについてはRelying Partyに依存する。
Crieitは誰でも投稿できるサービスです。 是非記事の投稿をお願いします。どんな軽い内容でも投稿できます。
また、「こんな記事が読みたいけど見つからない!」という方は是非記事投稿リクエストボードへ!
こじんまりと作業ログやメモ、進捗を書き残しておきたい方はボード機能をご利用ください。
ボードとは?
コメント