FIDO2サーバ実装に必要そうな仕様書「Server Requirements and Transport Binding Profile」を日本語訳する

Server Requirements and Transport Binding Profileの日本語訳をしたので残しておきます。

W3CのWebAuthnに関する仕様書(Web Authentication: An API for accessing Public Key Credentials - Level 2)と合わせて、FIDO2サーバの実装に重要な仕様書のはず。WebAuthnはリライングパーティ向けなのでFIDO2サーバの実装にはこちらが重要なのか?この仕様書でもWebAuthnと競合する場合にはこちらのドキュメントが優先される旨、FIDO2 Conformance Test(FIDO2サーバの認定を受けるために必要な適合性試験)についての言及があるので、確認が必要なはず。 FIDOアライアンスのドキュメント一覧のページからはリンクがないなど、このドキュメントの位置付けがよくわからない。

Server Requirements and Transport Binding Profile

Review Draft,July 02, 2018

概要

FIDO2は、Client-to-Authenticator Protocol (CTAP)を実装した認証器およびプアラットフォームやW3C WebAuthn仕様書を実装したブラウザの利用を通じてセキュアな認証を提供する。これらの認証器は、登録および認証要求の正当性を確認するサーバと通信することが期待されます。FIDO2サーバに対する多くの必須要件、アサーションフォーマットやアテステーションフォーマットやオプショナルな拡張機能などはW3C WebAuthn仕様書に含まれています。サーバの必須要件およびガイダンスに関する本仕様書は、サーバに関係のない認証器およびWebブラウザの詳細を残しつつ、FIDO2サーバの実装に役立てられるようにサーバに関する全ての要件を1つのドキュメントにまとめようとしている。

1 イントロダクション

この仕様書は、サーバ実装に関してW3C WebAuthnの仕様書からの情報を取り込んだ必須要件とガイダンスを提供する。サーバは、実装が連携して機能することを保証することからFIDOエコシステムにおいて非常に重要である。異なるアテステーションフォーマット(packed、AndroidTPMなど)、アテステーションモード(サロゲート、フル、ECDAAなど)、暗号化アルゴリズムRSA、ECDSAなど)というように、様々な仕様書に多くのオプション機能がある。これらの多様な機能を実装している認証器は、一般的にはメモリおよびまたはCPUに制限があり、先述のような様々な機能を実装することに制限がある消費者向けの電子機器である。したがって、サーバは可能な限り幅広い種類の認証器と互換性を持つことを保証するため、これらの機能を可能な限り多く実装することになる。

WebAuthnの仕様書の概念は非常にシンプルである:サーバに新しい認証器を登録するメソッドを提供し(navigator.credentials.create())、登録済の認証器を利用した認証をおこなう別のメソッドを提供している(navigator.credentials.get())。登録において、認証器はその製造時に認証器に組み込んだアテステーション秘密鍵を利用してアテステーションステートメントを作成し、登録プロセスでのroot-of-trustを提供する。登録処理で登録されたアカウントごとに新しいキーペアを作成され、登録で作成した秘密鍵は正当な認証であることを示すためサーバに送信するアサーションに対して署名する用途に利用される。以下のセクションでは登録とアテステーションの必須要件および認証とアサーションの必須要件について記述している。

サーバには特定の必須プロトコル(REST、SOAP伝書鳩量子テレポーテーションなど)は存在しない(ただし、セキュアなコミュニケーションチャンネルに関する要件は存在する)。サーバはブラウザ、プラットフォーム、認証器が作成するによって作成された何らかの形式のJavaScriptオブジェクトを受け取っていることが想定される。これらのオブジェクトは署名されているため、プロトコルは署名されたオブジェクトをその署名が不当となるような方法で変更してはならない(MUST NOT)が、そうではない場合はサーバにこれらのオブジェクトを送る任意の形式が利用できる。以下の必須要件とガイダンスは、これらのオブジェクトをサーバに対して送受信する方法に関する要件について定めていない。

この仕様書とWebAuthnの仕様書が競合する場合、WebAuthn仕様書が優先される。しかし、この仕様書がWebAuthn仕様書よりも優先とする説明や追記があり、WebブラウザにおいてWebAuthnを実装する方法についての多くの記述はサーバ実装には無関係である。

2 登録とアテステーション

サーバは登録をサポートするものとする(SHALL)。登録リクエストは、チャレンジを認証器に送信してレスポンスにCredentialCreationOptionsオブジェクト(または類似のもの)を受け取るという形を取る。PublicKeyCredentialresponse属性はシリアライズされたclientDataJSON属性およびシリアライズされたattestationObject属性の両方を有している。シリアライズ形式(例 base64urlエンコーディング)には、デシリアライズされたときに元のバイト構造がアテステーションにおいて署名されたものと同じであることという要件を除き、他の要件は存在しない。

サーバは登録リクエストごとにランダムなチャレンジを利用するものとする(SHALL)。チャレンジのランダム性の定義はこの仕様書の範囲外(詳細については[FIDOSecRef]を参照)ではあるが、同じチャレンジや単調増加するチャレンジ、その他単純なチャンレジを利用することは受け入れられず安全ではない。チャレンジの生成には暗号論的乱数生成器を利用することが期待される。

2.1 アテステーションの検証

サーバはアテステーションを検証するものとする(SHALL)。[WebAuthn]はアテステーションの検証方法を指定している。Relying Partyに対する要件はサーバにも標準である。AttestationResponseのフィールド名は[WebAuthn]仕様書のフィールド名および形式と一致しなくてもよい(MAY NOT)ことに注意する。アプリケーションとサーバが独自のフィールド名、形式で通信する可能性がある。[WebAuthn]に記載されている名前および形式は便宜上のものである。

サーバはアテステーション証明書チェーンを検証するものとする(SHALL)。

サーバはFIDO Metadata Service [FIDOMetadataService]を利用してアテステーションの検証をサポートしなければならない(MUST)。

サーバは、認証器のメタデータ属性に基づいて、認証器の許可・不許可、追加の認証要素の要求、リスク分析の実施に関するポリシーを持ってもよい(MAY)。

2.2 アテステーションタイプ

[WebAuthn]では複数のアテステーションタイプが定義されている。サーバはアテステーションフォーマットのうち1つをサポートしなければならない(MUST)。

  • サーバはbasicアテステーションをサポートしなければならない(MUST)
  • サーバはselfアテステーションをサポートしなければならない(MUST)
  • サーバはPrivacy CAアテステーションをサポートしてもよい(MAY)
  • サーバはElliptic Curve Direct Anonymousアテステーション(ECDAA)をサポートしてもよい(MAY)

2.3 アテステーションフォーマット

[WebAuthn]は複数のアテステーションフォーマットを定義しており、エコシステムの進歩に応じて[WebAuthn-Registries]レジストリに新しいアテステーションフォーマットが随時追加・更新される可能性がある。サーバは少なくとも1つのアテステーションフォーマットをサポートしなければならない(MUST)。

  • サーバはPackedアテステーションをサポートしなければならない(MUST):[WebAuthn]
  • サーバはTPMアテステーションをサポートしなければならない(MUST):[WebAuthn]
  • サーバはAndroid Keyアテステーションをサポートする必要がある(SHOULD):[WebAuthn]
  • サーバはU2Fアテステーションをサポートしなければならない(MUST):[WebAuthn]
  • サーバはAndroid SafteyNetアテステーションをサポートしなければならない(MUST):[WebAuthn]
  • サーバは、随時更新される[WebAuthn-Registries]に定義されている他のアテステーションフォーマットをサポートしてもよい(MAY)。認証器またはサーバが新しいアテステーションフォーマットを作成した場合、[WebAuthn-Registries]レジストリに登録する必要がある(SHOULD)。

2.3.1 Packedアテステーション

サーバは、[WebAuthn]に定義されている「Validation Procedure」に従ってPackedアテステーションを検証しなければならない(MUST)。

EXAMPLE 1

{
    "rawId": "sL39APyTmisrjh11vghaqNfuruLQmCfR0c1ryKtaQ81jkEhNa5u9xLTnkibvXC9YpzBLFwWEZ3k9CR_sxzm_pWYbBOtKxeZu9z2GT8b6QW4iQvRlyumCT3oENx_8401r",
    "id": "sL39APyTmisrjh11vghaqNfuruLQmCfR0c1ryKtaQ81jkEhNa5u9xLTnkibvXC9YpzBLFwWEZ3k9CR_sxzm_pWYbBOtKxeZu9z2GT8b6QW4iQvRlyumCT3oENx_8401r",
    "response": {
        "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJ1Vlg4OElnUmEwU1NyTUlSVF9xN2NSY2RmZ2ZSQnhDZ25fcGtwVUFuWEpLMnpPYjMwN3dkMU9MWFEwQXVOYU10QlIzYW1rNkhZenAtX1Z4SlRQcHdHdyIsIm9yaWdpbiI6Imh0dHBzOi8vd2ViYXV0aG4ub3JnIiwidG9rZW5CaW5kaW5nIjp7InN0YXR1cyI6Im5vdC1zdXBwb3J0ZWQifSwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9",
        "attestationObject": "o2NmbXRmcGFja2VkZ2F0dFN0bXSjY2FsZyZjc2lnWEgwRgIhAIsK0Wr9tmud-waIYoQw20UWi7DL_gDx_PNG3PB57eHLAiEAtRyd-4JI2pCVX-dDz4mbHc_AkvC3d_4qnBBa3n2I_hVjeDVjg1kCRTCCAkEwggHooAMCAQICEBWfe8LNiRjxKGuTSPqfM-IwCgYIKoZIzj0EAwIwSTELMAkGA1UEBhMCQ04xHTAbBgNVBAoMFEZlaXRpYW4gVGVjaG5vbG9naWVzMRswGQYDVQQDDBJGZWl0aWFuIEZJRE8yIENBLTEwIBcNMTgwNDExMDAwMDAwWhgPMjAzMzA0MTAyMzU5NTlaMG8xCzAJBgNVBAYTAkNOMR0wGwYDVQQKDBRGZWl0aWFuIFRlY2hub2xvZ2llczEiMCAGA1UECwwZQXV0aGVudGljYXRvciBBdHRlc3RhdGlvbjEdMBsGA1UEAwwURlQgQmlvUGFzcyBGSURPMiBVU0IwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASABnVcWfvJSbAVqNIKkliXvoMKsu_oLPiP7aCQlmPlSMcfEScFM7QkRnidTP7hAUOKlOmDPeIALC8qHddvTdtdo4GJMIGGMB0GA1UdDgQWBBR6VIJCgGLYiuevhJglxK-RqTSY8jAfBgNVHSMEGDAWgBRNO9jEZxUbuxPo84TYME-daRXAgzAMBgNVHRMBAf8EAjAAMBMGCysGAQQBguUcAgEBBAQDAgUgMCEGCysGAQQBguUcAQEEBBIEEEI4MkVENzNDOEZCNEU1QTIwCgYIKoZIzj0EAwIDRwAwRAIgJEtFo76I3LfgJaLGoxLP-4btvCdKIsEFLjFIUfDosIcCIDQav04cJPILGnPVPazCqfkVtBuyOmsBbx_v-ODn-JDAWQH_MIIB-zCCAaCgAwIBAgIQFZ97ws2JGPEoa5NI-p8z4TAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJDTjEdMBsGA1UECgwURmVpdGlhbiBUZWNobm9sb2dpZXMxHTAbBgNVBAMMFEZlaXRpYW4gRklETyBSb290IENBMCAXDTE4MDQxMDAwMDAwMFoYDzIwMzgwNDA5MjM1OTU5WjBJMQswCQYDVQQGEwJDTjEdMBsGA1UECgwURmVpdGlhbiBUZWNobm9sb2dpZXMxGzAZBgNVBAMMEkZlaXRpYW4gRklETzIgQ0EtMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABI5-YAnswRZlzKD6w-lv5Qg7lW1XJRHrWzL01mc5V91n2LYXNR3_S7mA5gupuTO5mjQw8xfqIRMHVr1qB3TedY-jZjBkMB0GA1UdDgQWBBRNO9jEZxUbuxPo84TYME-daRXAgzAfBgNVHSMEGDAWgBTRoZhNgX_DuWv2B2e9UBL-kEXxVDASBgNVHRMBAf8ECDAGAQH_AgEAMA4GA1UdDwEB_wQEAwIBBjAKBggqhkjOPQQDAgNJADBGAiEA-3-j0kBHoRFQwnhWbSHMkBaY7KF_TztINFN5ymDkwmUCIQDrCkPBiMHXvYg-kSRgVsKwuVtYonRvC588qRwpLStZ7FkB3DCCAdgwggF-oAMCAQICEBWfe8LNiRjxKGuTSPqfM9YwCgYIKoZIzj0EAwIwSzELMAkGA1UEBhMCQ04xHTAbBgNVBAoMFEZlaXRpYW4gVGVjaG5vbG9naWVzMR0wGwYDVQQDDBRGZWl0aWFuIEZJRE8gUm9vdCBDQTAgFw0xODA0MDEwMDAwMDBaGA8yMDQ4MDMzMTIzNTk1OVowSzELMAkGA1UEBhMCQ04xHTAbBgNVBAoMFEZlaXRpYW4gVGVjaG5vbG9naWVzMR0wGwYDVQQDDBRGZWl0aWFuIEZJRE8gUm9vdCBDQTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJ3wCm47zF9RMtW-pPlkEHTVTLfSYBlsidz7zOAUiuV6k36PvtKAI_-LZ8MiC9BxQUfUrfpLY6klw344lwLq7POjQjBAMB0GA1UdDgQWBBTRoZhNgX_DuWv2B2e9UBL-kEXxVDAPBgNVHRMBAf8EBTADAQH_MA4GA1UdDwEB_wQEAwIBBjAKBggqhkjOPQQDAgNIADBFAiEAt7E9ZQYxnhfsSk6c1dSmFNnJGoU3eJiycs2DoWh7-IoCIA9iWJH8h-UOAaaPK66DtCLe6GIxdpIMv3kmd1PRpWqsaGF1dGhEYXRhWOSVaQiPHs7jIylUA129ENfK45EwWidRtVm7j9fLsim91EEAAAABQjgyRUQ3M0M4RkI0RTVBMgBgsL39APyTmisrjh11vghaqNfuruLQmCfR0c1ryKtaQ81jkEhNa5u9xLTnkibvXC9YpzBLFwWEZ3k9CR_sxzm_pWYbBOtKxeZu9z2GT8b6QW4iQvRlyumCT3oENx_8401rpQECAyYgASFYIFkdweEE6mWiIAYPDoKz3881Aoa4sn8zkTm0aPKKYBvdIlggtlG32lxrang8M0tojYJ36CL1VMv2pZSzqR_NfvG88bA"
    }
};

2.3.2 TPMアテステーション

サーバは、[WebAuthn]に定義されている「Validation Procedure」に従ってTPMアテステーションを検証しなければならない(MUST)。

EXAMPLE 2

{
    "rawId": "hWzdFiPbOMQ5KNBsMhs-Zeh8F0iTHrH63YKkrxJFgjQ",
    "id": "hWzdFiPbOMQ5KNBsMhs-Zeh8F0iTHrH63YKkrxJFgjQ",
    "response": {
        "clientDataJSON": "ew0KCSJ0eXBlIiA6ICJ3ZWJhdXRobi5jcmVhdGUiLA0KCSJjaGFsbGVuZ2UiIDogIndrNkxxRVhBTUFacHFjVFlsWTJ5b3I1RGppeUlfYjFneTluRE90Q0IxeUdZbm1fNFdHNFVrMjRGQXI3QXhUT0ZmUU1laWdrUnhPVExaTnJMeEN2Vl9RIiwNCgkib3JpZ2luIiA6ICJodHRwczovL3dlYmF1dGhuLm9yZyIsDQoJInRva2VuQmluZGluZyIgOiANCgl7DQoJCSJzdGF0dXMiIDogInN1cHBvcnRlZCINCgl9DQp9",
        "attestationObject": "o2NmbXRjdHBtaGF1dGhEYXRhWQFnlWkIjx7O4yMpVANdvRDXyuORMFonUbVZu4_Xy7IpvdRFAAAAAAiYcFjK3EuBtuEw3lDcvpYAIIVs3RYj2zjEOSjQbDIbPmXofBdIkx6x-t2CpK8SRYI0pAEDAzkBACBZAQDF2m9Nk1e94gL1xVjNCjFW0lTy4K2atXkx-YJrdH3hrE8p1gcIdNzleRDhmERJnY5CRwM5sXDQIrUBq4jpwvTtMC5HGccN6-iEJAPtm9_CJzCmGhtw9hbF8bcAys94RhN9xLLUaajhWqtPrYZXCEAi0o9E2QdTIxJrcAfJgZOf33JMr0--R1BAQxpOoGRDC8ss-tfQW9ufZLWw4JUuz4Z5Jz1sbfqBYB8UUDMWoT0HgsMaPmvd7T17xGvB-pvvDf-Dt96vFGtYLEZEgho8Yu26pr5CK_BOQ-2vX9N4MIYVPXNhogMGGmKYqybhM3yhye0GdBpZBUd5iOcgME6uGJ1_IUMBAAFnYXR0U3RtdKZjdmVyYzIuMGNhbGc5__5jc2lnWQEAcV1izWGUWIs0DEOZNQGdriNNXo6nbrGDLzEAeswCK9njYGCLmOkHVgSyafhsjCEMZkQmuPUmEOMDKosqxup_tiXQwG4yCW9TyWoINWGayQ4vcr6Ys-l6KMPkg__d2VywhfonnTJDBfE_4BIRD60GR0qBzTarthDHQFMqRtoUtuOsTF5jedU3EQPojRA5iCNC2naCCZuMSURdlPmhlW5rAaRZVF41ZZECi5iFOM2rO0UpGuQSLUvr1MqQOsDytMf7qWZMvwT_5_8BF6GNdB2l2VzmIJBbV6g8z7dj0fRkjlCXBp8UG2LvTq5SsfugrRWXOJ8BkdMplPfl0mz6ssU_n2N4NWOCWQS2MIIEsjCCA5qgAwIBAgIQEyidpWZzRxOSMNfrAvV1fzANBgkqhkiG9w0BAQsFADBBMT8wPQYDVQQDEzZOQ1UtTlRDLUtFWUlELTE1OTFENEI2RUFGOThEMDEwNDg2NEI2OTAzQTQ4REQwMDI2MDc3RDMwHhcNMTgwNTIwMTYyMDQ0WhcNMjgwNTIwMTYyMDQ0WjAAMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvQ6XK2ujM11E7x4SL34p252ncyQTd3-4r5ALQhBbFKS95gUsuENTG-48GBQwu48i06cckm3eH20TUeJvn4-pj6i8LFOrIK14T3P3GFzbxgQLq1KVm63JWDdEXk789JgzQjHNO7DZFKWTEiktwmBUPUA88TjQcXOtrR5EXTrt1FzGzabOepFann3Ny_XtxI8lDZ3QLwPLJfmk7puGtkGNaXOsRC7GLAnoEB7UWvjiyKG6HAtvVTgxcW5OQnHFb9AHycU5QdukXrP0njdCpLCRR0Nq6VMKmVU3MaGh-DCwYEB32sPNPdDkPDWyk16ItwcmXqfSBV5ZOr8ifvcXbCWUWwIDAQABo4IB5TCCAeEwDgYDVR0PAQH_BAQDAgeAMAwGA1UdEwEB_wQCMAAwbQYDVR0gAQH_BGMwYTBfBgkrBgEEAYI3FR8wUjBQBggrBgEFBQcCAjBEHkIAVABDAFAAQQAgACAAVAByAHUAcwB0AGUAZAAgACAAUABsAGEAdABmAG8AcgBtACAAIABJAGQAZQBuAHQAaQB0AHkwEAYDVR0lBAkwBwYFZ4EFCAMwSgYDVR0RAQH_BEAwPqQ8MDoxODAOBgVngQUCAwwFaWQ6MTMwEAYFZ4EFAgIMB05QQ1Q2eHgwFAYFZ4EFAgEMC2lkOjRFNTQ0MzAwMB8GA1UdIwQYMBaAFMISqVvO-lb4wMFvsVvdAzRHs3qjMB0GA1UdDgQWBBSv4kXTSA8i3NUM0q57lrWpM8p_4TCBswYIKwYBBQUHAQEEgaYwgaMwgaAGCCsGAQUFBzAChoGTaHR0cHM6Ly9hemNzcHJvZG5jdWFpa3B1Ymxpc2guYmxvYi5jb3JlLndpbmRvd3MubmV0L25jdS1udGMta2V5aWQtMTU5MWQ0YjZlYWY5OGQwMTA0ODY0YjY5MDNhNDhkZDAwMjYwNzdkMy8zYjkxOGFlNC0wN2UxLTQwNTktOTQ5MS0wYWQyNDgxOTA4MTguY2VyMA0GCSqGSIb3DQEBCwUAA4IBAQAs-vqdkDX09fNNYqzbv3Lh0vl6RgGpPGl-MYgO8Lg1I9UKvEUaaUHm845ABS8m7r9p22RCWO6TSEPS0YUYzAsNuiKiGVna4nB9JWZaV9GDS6aMD0nJ8kNciorDsV60j0Yb592kv1VkOKlbTF7-Z10jaapx0CqhxEIUzEBb8y9Pa8oOaQf8ORhDHZp-mbn_W8rUzXSDS0rFbWKaW4tGpVoKGRH-f9vIeXxGlxVS0wqqRm_r-h1aZInta0OOiL_S4367gZyeLL3eUnzdd-eYySYn2XINPbVacK8ZifdsLMwiNtz5uM1jbqpEn2UoB3Hcdn0hc12jTLPWFfg7GiKQ0hk9WQXsMIIF6DCCA9CgAwIBAgITMwAAAQDiBsSROVGXhwAAAAABADANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE2MDQGA1UEAxMtTWljcm9zb2Z0IFRQTSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAyMDE0MB4XDTE3MDIwMTE3NDAyNFoXDTI5MTIzMTE3NDAyNFowQTE_MD0GA1UEAxM2TkNVLU5UQy1LRVlJRC0xNTkxRDRCNkVBRjk4RDAxMDQ4NjRCNjkwM0E0OEREMDAyNjA3N0QzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA9IwUMSiQUbrQR0NLkKR-9RB8zfHYdlmDB0XN_m8qrNHKRJ__lBOR-mwU_h3MFRZF6X3ZZwka1DtwBdzLFV8lVu33bc15stjSd6B22HRRKQ3sIns5AYQxg0eX2PtWCJuIhxdM_jDjP2hq9Yvx-ibt1IO9UZwj83NGxXc7Gk2UvCs9lcFSp6U8zzl5fGFCKYcxIKH0qbPrzjlyVyZTKwGGSTeoMMEdsZiq-m_xIcrehYuHg-FAVaPLLTblS1h5cu80-ruFUm5Xzl61YjVU9tAV_Y4joAsJ5QP3VPocFhr5YVsBVYBiBcQtr5JFdJXZWWEgYcFLdAFUk8nJERS7-5xLuQIDAQABo4IBizCCAYcwCwYDVR0PBAQDAgGGMBsGA1UdJQQUMBIGCSsGAQQBgjcVJAYFZ4EFCAMwFgYDVR0gBA8wDTALBgkrBgEEAYI3FR8wEgYDVR0TAQH_BAgwBgEB_wIBADAdBgNVHQ4EFgQUwhKpW876VvjAwW-xW90DNEezeqMwHwYDVR0jBBgwFoAUeowKzi9IYhfilNGuVcFS7HF0pFYwcAYDVR0fBGkwZzBloGOgYYZfaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jcmwvTWljcm9zb2Z0JTIwVFBNJTIwUm9vdCUyMENlcnRpZmljYXRlJTIwQXV0aG9yaXR5JTIwMjAxNC5jcmwwfQYIKwYBBQUHAQEEcTBvMG0GCCsGAQUFBzAChmFodHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NlcnRzL01pY3Jvc29mdCUyMFRQTSUyMFJvb3QlMjBDZXJ0aWZpY2F0ZSUyMEF1dGhvcml0eSUyMDIwMTQuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQAKc9z1UUBAaybIVnK8yL1N1iGJFFFFw_PpkxW76hgQhUcCxNFQskfahfFzkBD05odVC1DKyk2PyOle0G86FCmZiJa14MtKNsiu66nVqk2hr8iIcu-cYEsgb446yIGd1NblQKA1C_28F2KHm8YRgcFtRSkWEMuDiVMa0HDU8aI6ZHO04Naj86nXeULJSZsA0pQwNJ04-QJP3MFQzxQ7md6D-pCx-LVA-WUdGxT1ofaO5NFxq0XjubnZwRjQazy_m93dKWp19tbBzTUKImgUKLYGcdmVWXAxUrkxHN2FbZGOYWfmE2TGQXS2Z-g4YAQo1PleyOav3HNB8ti7u5HpI3t9a73xuECy2gFcZQ24DJuBaQe4mU5I_hPiAa-822nPPL6w8m1eegxhHf7ziRW_hW8s1cvAZZ5Jpev96zL_zRv34MsRWhKwLbu2oOCSEYYh8D8DbQZjmsxlUYR_q1cP8JKiIo6NNJ85g7sjTZgXxeanA9wZwqwJB-P98VdVslC17PmVu0RHOqRtxrht7OFT7Z10ecz0tj9ODXrv5nmBktmbgHRirRMl84wp7-PJhTXdHbxZv-OoL4HP6FxyDbHxLB7QmR4-VoEZN0vsybb1A8KEj2pkNY_tmxHH6k87euM99bB8FHrW9FNrXCGL1p6-PYtiky52a5YQZGT8Hz-ZnxobTmhjZXJ0SW5mb1ih_1RDR4AXACIAC7xZ9N_ZpqQtw7hmr_LfDRmCa78BS2erCtbrsXYwa4AHABSsnz8FacZi-wkUkfHu4xjG8MPfmwAAAAGxWkjHaED549jznwUBqeDEpT-7xBMAIgALcSGuv6a5r9BwMvQvCSXg7GdAjdWZpXv6D4DH8VYBCE8AIgALAVI0eQ_AAZjNvrhUEMK2q4wxuwIFOnHIDF0Qljhf47RncHViQXJlYVkBNgABAAsABgRyACCd_8vzbDg65pn7mGjcbcuJ1xU4hL4oA5IsEkFYv60irgAQABAIAAAAAAABAMXab02TV73iAvXFWM0KMVbSVPLgrZq1eTH5gmt0feGsTynWBwh03OV5EOGYREmdjkJHAzmxcNAitQGriOnC9O0wLkcZxw3r6IQkA-2b38InMKYaG3D2FsXxtwDKz3hGE33EstRpqOFaq0-thlcIQCLSj0TZB1MjEmtwB8mBk5_fckyvT75HUEBDGk6gZEMLyyz619Bb259ktbDglS7PhnknPWxt-oFgHxRQMxahPQeCwxo-a93tPXvEa8H6m-8N_4O33q8Ua1gsRkSCGjxi7bqmvkIr8E5D7a9f03gwhhU9c2GiAwYaYpirJuEzfKHJ7QZ0GlkFR3mI5yAwTq4YnX8"
    }
};

2.3.3 Android Keyアテステーション例

サーバは、[WebAuthn]に定義されている「Validation Procedure」に従ってAndroid Keyアテステーションを検証する必要がある(SHOULD)。

ISSUE 1Android Keyアテステーションの例が必要

Android Keyアテステーション例を記載する必要がある。

2.3.4 Android SafetyNetアテステーション例

サーバは、[WebAuthn]に定義されている「Validation Procedure」に従ってAndroid SafetyNetアテステーションを検証しなければならない(MUST)。

EXAMPLE 3

{
    "rawId": "qCXEfJ-dEoBlWqIl0iq2p_gj13HSg7r_MA7xOcOiO8RkCrYNmQHIjV9yhZVASr87cUsflo7DNuuvGsnrlTl1ig",
    "id": "qCXEfJ-dEoBlWqIl0iq2p_gj13HSg7r_MA7xOcOiO8RkCrYNmQHIjV9yhZVASr87cUsflo7DNuuvGsnrlTl1ig",
    "response": {
        "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJEa1hCdWRCa2wzTzBlTUV5SGZBTVgxT2tRbHV4c2hjaW9WU3dITVJMUlhtd044SXJldHg3cWJ0MWx3Y0p4d0FxWUU0SUxTZjVwd3lHMEhXSWtEekVMUT09Iiwib3JpZ2luIjoid2ViYXV0aG4ub3JnIiwiaGFzaEFsZyI6IlNIQS0yNTYifQ",
        "attestationObject": "o2hhdXRoRGF0YVjElWkIjx7O4yMpVANdvRDXyuORMFonUbVZu4_Xy7IpvdRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQKglxHyfnRKAZVqiJdIqtqf4I9dx0oO6_zAO8TnDojvEZAq2DZkByI1fcoWVQEq_O3FLH5aOwzbrrxrJ65U5dYqlAQIDJiABIVggh5OJfYRDzVGIowKqU57AnoVjjdmmjGi9zlMkjAVV9DAiWCDr0iSi0viIKNPMTIdN28gWNmkcwOr6DQx66MPff3Odm2NmbXRxYW5kcm9pZC1zYWZldHluZXRnYXR0U3RtdKJjdmVyaDEyNjg1MDIzaHJlc3BvbnNlWRSnZXlKaGJHY2lPaUpTVXpJMU5pSXNJbmcxWXlJNld5Sk5TVWxGYVdwRFEwRXpTMmRCZDBsQ1FXZEpTVmxyV1c4MVJqQm5PRFpyZDBSUldVcExiMXBKYUhaalRrRlJSVXhDVVVGM1ZrUkZURTFCYTBkQk1WVkZRbWhOUTFaV1RYaElha0ZqUW1kT1ZrSkJiMVJHVldSMllqSmtjMXBUUWxWamJsWjZaRU5DVkZwWVNqSmhWMDVzWTNwRmJFMURUVWRCTVZWRlFYaE5ZMUl5T1haYU1uaHNTVVZzZFdSSFZubGliVll3U1VWR01XUkhhSFpqYld3d1pWTkNTRTE2UVdWR2R6QjRUbnBGZVUxRVVYaE5la1UwVGtST1lVWjNNSGhQUkVWNVRVUk5kMDFFUVhkTlJFSmhUVWQzZUVONlFVcENaMDVXUWtGWlZFRnNWbFJOVWsxM1JWRlpSRlpSVVVsRVFYQkVXVmQ0Y0ZwdE9YbGliV3hvVFZKWmQwWkJXVVJXVVZGSVJFRXhUbUl6Vm5Wa1IwWndZbWxDVjJGWFZqTk5VazEzUlZGWlJGWlJVVXRFUVhCSVlqSTVibUpIVldkVFZ6VnFUVkp6ZDBkUldVUldVVkZFUkVKS2FHUklVbXhqTTFGMVdWYzFhMk50T1hCYVF6VnFZakl3ZDJkblJXbE5RVEJIUTFOeFIxTkpZak5FVVVWQ1FWRlZRVUUwU1VKRWQwRjNaMmRGUzBGdlNVSkJVVU5WYWpoM1dXOVFhWGhMWW1KV09ITm5XV2QyVFZSbVdDdGtTWE5HVkU5clowdFBiR2hVTUdrd1ltTkVSbHBMTW5KUGVFcGFNblZUVEZOV2FGbDJhWEJhVGtVelNFcFJXWFYxV1hkR2FtbDVLM2xyWm1GMFFVZFRhbEo2UmpGaU16RjFORE12TjI5SE5XcE5hRE5UTXpkaGJIZHFWV0k0UTFkcFZIaHZhWEJXVDFsM1MwdDZkVlY1YTNGRlEzUnFiR2hLTkVGclYyRkVVeXRhZUV0RmNVOWhaVGwwYmtOblpVaHNiRnBGTDA5U1oyVk5ZWGd5V0U1RGIwZzJjM0pVUlZKamEzTnFlbHBhY2tGWGVFdHpaR1oyVm5KWVRucERVamxFZUZaQlUzVkpOa3g2ZDJnNFJGTnNNa1ZQYjJ0aWMyRnVXaXNyTDBweFRXVkJRa1ptVUhkcWVYZHlZakJ3Y2tWVmVUQndZV1ZXYzNWa0t6QndaV1Y0U3k4MUswVTJhM0JaUjBzMFdrc3libXR2Vmt4MVowVTFkR0ZJY2tGcU9ETlJLMUJQWW1KMlQzcFhZMFpyY0c1V1MzbHFielpMVVVGdFdEWlhTa0ZuVFVKQlFVZHFaMmRHUjAxSlNVSlJha0ZVUW1kT1ZraFRWVVZFUkVGTFFtZG5ja0puUlVaQ1VXTkVRVlJCWkVKblRsWklVa1ZGUm1wQlZXZG9TbWhrU0ZKc1l6TlJkVmxYTld0amJUbHdXa00xYW1JeU1IZGhRVmxKUzNkWlFrSlJWVWhCVVVWRldFUkNZVTFETUVkRFEzTkhRVkZWUmtKNlFVTm9hVVp2WkVoU2QwOXBPSFpqUjNSd1RHMWtkbUl5WTNaYU0wNTVUV2s1U0ZaR1RraFRWVVpJVFhrMWFtTnVVWGRMVVZsSlMzZFpRa0pSVlVoTlFVZEhTRmRvTUdSSVFUWk1lVGwyV1ROT2QweHVRbkpoVXpWdVlqSTVia3d3WkZWVk1HUktVVlZqZWsxQ01FZEJNVlZrUkdkUlYwSkNVVWM0U1hKUmRFWlNOa05WVTJ0cGEySXpZV2x0YzIweU5tTkNWRUZOUW1kT1ZraFNUVUpCWmpoRlFXcEJRVTFDT0VkQk1WVmtTWGRSV1UxQ1lVRkdTR1pEZFVaRFlWb3pXakp6VXpORGFIUkRSRzlJTm0xbWNuQk1UVU5GUjBFeFZXUkpRVkZoVFVKbmQwUkJXVXRMZDFsQ1FrRklWMlZSU1VaQmVrRkpRbWRhYm1kUmQwSkJaMGwzVFZGWlJGWlNNR1pDUTI5M1MwUkJiVzlEVTJkSmIxbG5ZVWhTTUdORWIzWk1NazU1WWtNMWQyRXlhM1ZhTWpsMlduazVTRlpHVGtoVFZVWklUWGsxYW1OdGQzZEVVVmxLUzI5YVNXaDJZMDVCVVVWTVFsRkJSR2RuUlVKQlJpOVNlazV1UXpWRWVrSlZRblJ1YURKdWRFcE1WMFZSYURsNlJXVkdXbVpRVERsUmIydHliRUZ2V0dkcVYyZE9PSEJUVWxVeGJGWkhTWEIwZWsxNFIyaDVNeTlQVWxKYVZHRTJSREpFZVRob2RrTkVja1pKTXl0c1Exa3dNVTFNTlZFMldFNUZOVkp6TW1ReFVtbGFjRTF6ZWtRMFMxRmFUa2N6YUZvd1FrWk9VUzlqYW5KRGJVeENUMGRMYTBWVk1XUnRRVmh6UmtwWVNtbFBjakpEVGxSQ1QxUjFPVVZpVEZkb1VXWmtRMFl4WW5kNmVYVXJWelppVVZOMk9GRkVialZQWkUxVEwxQnhSVEZrUldkbGRDODJSVWxTUWpjMk1VdG1XbEVyTDBSRk5reHdNMVJ5V2xSd1QwWkVSR2RZYUN0TVowZFBjM2RvUld4cU9XTXpkbHBJUjBwdWFHcHdkRGh5YTJKcGNpOHlkVXhIWm5oc1ZsbzBTekY0TlVSU1RqQlFWVXhrT1hsUVUyMXFaeXRoYWpFcmRFaDNTVEZ0VVcxYVZsazNjWFpQTlVSbmFFOTRhRXBOUjJ4Nk5teE1hVnB0ZW05blBTSXNJazFKU1VWWVJFTkRRVEJUWjBGM1NVSkJaMGxPUVdWUGNFMUNlamhqWjFrMFVEVndWRWhVUVU1Q1oydHhhR3RwUnpsM01FSkJVWE5HUVVSQ1RVMVRRWGRJWjFsRVZsRlJURVY0WkVoaVJ6bHBXVmQ0VkdGWFpIVkpSa3AyWWpOUloxRXdSV2RNVTBKVFRXcEZWRTFDUlVkQk1WVkZRMmhOUzFJeWVIWlpiVVp6VlRKc2JtSnFSVlJOUWtWSFFURlZSVUY0VFV0U01uaDJXVzFHYzFVeWJHNWlha0ZsUm5jd2VFNTZRVEpOVkZWM1RVUkJkMDVFU21GR2R6QjVUVlJGZVUxVVZYZE5SRUYzVGtSS1lVMUdVWGhEZWtGS1FtZE9Wa0pCV1ZSQmJGWlVUVkkwZDBoQldVUldVVkZMUlhoV1NHSXlPVzVpUjFWblZraEtNV016VVdkVk1sWjVaRzFzYWxwWVRYaEtWRUZxUW1kT1ZrSkJUVlJJUldSMllqSmtjMXBUUWtwaWJsSnNZMjAxYkdSRFFrSmtXRkp2WWpOS2NHUklhMmRTZWsxM1oyZEZhVTFCTUVkRFUzRkhVMGxpTTBSUlJVSkJVVlZCUVRSSlFrUjNRWGRuWjBWTFFXOUpRa0ZSUkV0VmEzWnhTSFl2VDBwSGRXOHlia2xaWVU1V1YxaFJOVWxYYVRBeFExaGFZWG8yVkVsSVRFZHdMMnhQU2lzMk1EQXZOR2hpYmpkMmJqWkJRVUl6UkZaNlpGRlBkSE0zUnpWd1NEQnlTbTV1VDBaVlFVczNNVWMwYm5wTFRXWklRMGRWYTNOWEwyMXZibUVyV1RKbGJVcFJNazRyWVdsamQwcExaWFJRUzFKVFNXZEJkVkJQUWpaQllXaG9PRWhpTWxoUE0yZzVVbFZyTWxRd1NFNXZkVUl5Vm5wNGIwMVliR3Q1VnpkWVZWSTFiWGMyU210TVNHNUJOVEpZUkZadlVsUlhhMDUwZVRWdlEwbE9USFpIYlc1U2Mwb3hlbTkxUVhGWlIxWlJUV012TjNONUt5OUZXV2hCVEhKV1NrVkJPRXRpZEhsWUszSTRjMjUzVlRWRE1XaFZjbmRoVnpaTlYwOUJVbUU0Y1VKd1RsRmpWMVJyWVVsbGIxbDJlUzl6UjBsS1JXMXFVakIyUmtWM1NHUndNV05UWVZkSmNqWXZOR2MzTW00M1QzRllkMlpwYm5VM1dsbFhPVGRGWm05UFUxRktaVUY2UVdkTlFrRkJSMnBuWjBWNlRVbEpRa3g2UVU5Q1owNVdTRkU0UWtGbU9FVkNRVTFEUVZsWmQwaFJXVVJXVWpCc1FrSlpkMFpCV1VsTGQxbENRbEZWU0VGM1JVZERRM05IUVZGVlJrSjNUVU5OUWtsSFFURlZaRVYzUlVJdmQxRkpUVUZaUWtGbU9FTkJVVUYzU0ZGWlJGWlNNRTlDUWxsRlJraG1RM1ZHUTJGYU0xb3ljMU16UTJoMFEwUnZTRFp0Wm5Kd1RFMUNPRWRCTVZWa1NYZFJXVTFDWVVGR1NuWnBRakZrYmtoQ04wRmhaMkpsVjJKVFlVeGtMMk5IV1ZsMVRVUlZSME5EYzBkQlVWVkdRbmRGUWtKRGEzZEtla0ZzUW1kbmNrSm5SVVpDVVdOM1FWbFpXbUZJVWpCalJHOTJUREk1YW1NelFYVmpSM1J3VEcxa2RtSXlZM1phTTA1NVRXcEJlVUpuVGxaSVVqaEZTM3BCY0UxRFpXZEtZVUZxYUdsR2IyUklVbmRQYVRoMldUTktjMHh1UW5KaFV6VnVZakk1Ymt3eVpIcGpha2wyV2pOT2VVMXBOV3BqYlhkM1VIZFpSRlpTTUdkQ1JHZDNUbXBCTUVKbldtNW5VWGRDUVdkSmQwdHFRVzlDWjJkeVFtZEZSa0pSWTBOQlVsbGpZVWhTTUdOSVRUWk1lVGwzWVRKcmRWb3lPWFphZVRsNVdsaENkbU15YkRCaU0wbzFUSHBCVGtKbmEzRm9hMmxIT1hjd1FrRlJjMFpCUVU5RFFWRkZRVWhNWlVwc2RWSlVOMkoyY3pJMlozbEJXamh6YnpneGRISlZTVk5rTjA4ME5YTnJSRlZ0UVdkbE1XTnVlR2hITVZBeVkwNXRVM2hpVjNOdmFVTjBNbVYxZURsTVUwUXJVRUZxTWt4SldWSkdTRmN6TVM4MmVHOXBZekZyTkhSaVYxaHJSRU5xYVhJek4zaFVWRTV4VWtGTlVGVjVSbEpYVTJSMmRDdHViRkJ4ZDI1aU9FOWhNa2t2YldGVFNuVnJZM2hFYWs1VFpuQkVhQzlDWkRGc1drNW5aR1F2T0dOTVpITkZNeXQzZVhCMVprbzVkVmhQTVdsUmNHNW9PWHBpZFVaSmQzTkpUMDVIYkRGd00wRTRRMmQ0YTNGSkwxVkJhV2d6U21GSFQzRmpjR05rWVVOSmVtdENZVkk1ZFZsUk1WZzBhekpXWnpWQlVGSk1iM1Y2Vm5rM1lUaEpWbXMyZDNWNU5uQnRLMVEzU0ZRMFRGazRhV0pUTlVaRldteG1RVVpNVTFjNFRuZHpWbm81VTBKTE1sWnhiakZPTUZCSlRXNDFlRUUyVGxwV1l6ZHZPRE0xUkV4QlJuTm9SVmRtUXpkVVNXVXpaejA5SWwxOS5leUp1YjI1alpTSTZJbXhYYTBscWVEZFBOSGxOY0ZaQlRtUjJVa1JZZVhWUFVrMUdiMjVWWWxaYWRUUXZXSGszU1hCMlpGSkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVUZCUVVGQlFVRkJRVkZMWjJ4NFNIbG1ibEpMUVZwV2NXbEtaRWx4ZEhGbU5FazVaSGd3YjA4MkwzcEJUemhVYmtSdmFuWkZXa0Z4TWtSYWEwSjVTVEZtWTI5WFZsRkZjUzlQTTBaTVNEVmhUM2Q2WW5KeWVISktOalZWTldSWmNXeEJVVWxFU21sQlFrbFdaMmRvTlU5S1psbFNSSHBXUjBsdmQwdHhWVFUzUVc1dlZtcHFaRzF0YWtkcE9YcHNUV3RxUVZaV09VUkJhVmREUkhJd2FWTnBNSFpwU1V0T1VFMVVTV1JPTWpoblYwNXRhMk4zVDNJMlJGRjROalpOVUdabU0wOWtiU3QxTm1WS2NVeENiREZJTWxNeWRISkJRa2hNYVc1cmJuTjVWazFRYlM5Q1RsVldXakpLUm14eU9EQWlMQ0owYVcxbGMzUmhiWEJOY3lJNk1UVXlPRGt4TVRZek5ETTROU3dpWVhCclVHRmphMkZuWlU1aGJXVWlPaUpqYjIwdVoyOXZaMnhsTG1GdVpISnZhV1F1WjIxeklpd2lZWEJyUkdsblpYTjBVMmhoTWpVMklqb2lTazlETTFWcmMyeHpkVlo2TVRObFQzQnVSa2s1UW5CTWIzRkNaemxyTVVZMlQyWmhVSFJDTDBkcVRUMGlMQ0pqZEhOUWNtOW1hV3hsVFdGMFkyZ2lPbVpoYkhObExDSmhjR3REWlhKMGFXWnBZMkYwWlVScFoyVnpkRk5vWVRJMU5pSTZXeUpIV0ZkNU9GaEdNM1pKYld3ekwwMW1ibTFUYlhsMVMwSndWRE5DTUdSWFlraFNVaTgwWTJkeEsyZEJQU0pkTENKaVlYTnBZMGx1ZEdWbmNtbDBlU0k2Wm1Gc2MyVXNJbUZrZG1salpTSTZJbEpGVTFSUFVrVmZWRTlmUmtGRFZFOVNXVjlTVDAwc1RFOURTMTlDVDA5VVRFOUJSRVZTSW4wLmlDRjZEMm9zOERZdURWT250M3pESkIybVNYblpqdFdKdGxfanpTRHg1TXJSQzlBMmZtRkJaNno1a3BRWjJNaVE3b290ajlXa0hNZ3hxSWhyWDNkbGgyUE9IQXdrSVMzNHlTakxWTnNTUHByRTg0ZVpncVNGTE1FWVQwR1IyZVZMSEFNUE44bjVSOEs2YnVET0dGM25TaTZHS3pHNTdabGw4Q1NvYjJ5aUFTOXI3c3BkQTZIMFRESC1OR3pTZGJNSUlkOGZaRDFkekZLTlFyNzdiNmxiSUFGZ1FiUlpCcm5wLWUtSDRpSDZkMjFvTjJOQVlSblI1WVVSYWNQNmtHR2oyY0Z4c3dFMjkwOHd4djloaVlOS05vamVldThYYzRJdDdQYmhsQXVPN3l3aFFGQTgxaVBDQ0ZtMTFCOGNmVVhiV0E4bF8ydHROUEJFTUdNNi1aNlZ5UQ"
    }
};

2.3.5 U2Fアテステーション

サーバは、[WebAuthn]に定義されている「Validation Procedure」に従ってU2Fアテステーションを検証しなければならない(MUST)。

EXAMPLE 4

{
    "rawId": "Bo-VjHOkJZy8DjnCJnIc0Oxt9QAz5upMdSJxNbd-GyAo6MNIvPBb9YsUlE0ZJaaWXtWH5FQyPS6bT_e698IirQ==",
    "id": "Bo-VjHOkJZy8DjnCJnIc0Oxt9QAz5upMdSJxNbd-GyAo6MNIvPBb9YsUlE0ZJaaWXtWH5FQyPS6bT_e698IirQ==",
    "response": {
        "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEgwRgIhAO-683ISJhKdmUPmVbQuYZsp8lkD7YJcInHS3QOfbrioAiEAzgMJ499cBczBw826r1m55Jmd9mT4d1iEXYS8FbIn8MpjeDVjgVkCSDCCAkQwggEuoAMCAQICBFVivqAwCwYJKoZIhvcNAQELMC4xLDAqBgNVBAMTI1l1YmljbyBVMkYgUm9vdCBDQSBTZXJpYWwgNDU3MjAwNjMxMCAXDTE0MDgwMTAwMDAwMFoYDzIwNTAwOTA0MDAwMDAwWjAqMSgwJgYDVQQDDB9ZdWJpY28gVTJGIEVFIFNlcmlhbCAxNDMyNTM0Njg4MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAESzMfdz2BRLmZXL5FhVF-F1g6pHYjaVy-haxILIAZ8sm5RnrgRbDmbxMbLqMkPJH9pgLjGPP8XY0qerrnK9FDCaM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwCwYJKoZIhvcNAQELA4IBAQCsFtmzbrazqbdtdZSzT1n09z7byf3rKTXra0Ucq_QdJdPnFhTXRyYEynKleOMj7bdgBGhfBefRub4F226UQPrFz8kypsr66FKZdy7bAnggIDzUFB0-629qLOmeOVeAMmOrq41uxICn3whK0sunt9bXfJTD68CxZvlgV8r1_jpjHqJqQzdio2--z0z0RQliX9WvEEmqfIvHaJpmWemvXejw1ywoglF0xQ4Gq39qB5CDe22zKr_cvKg1y7sJDvHw2Z4Iab_p5WdkxCMObAV3KbAQ3g7F-czkyRwoJiGOqAgau5aRUewWclryqNled5W8qiJ6m5RDIMQnYZyq-FTZgpjXaGF1dGhEYXRhWMRJlg3liA6MaHQ0Fw9kdmBbj-SuuaKGMseZXPO6gx2XY0EAAAAAAAAAAAAAAAAAAAAAAAAAAABABo-VjHOkJZy8DjnCJnIc0Oxt9QAz5upMdSJxNbd-GyAo6MNIvPBb9YsUlE0ZJaaWXtWH5FQyPS6bT_e698IiraUBAgMmIAEhWCA1c9AIeH5sN6x1Q-2qR7v255tkeGbWs0ECCDw35kJGBCJYIBjTUxruadjFFMnWlR5rPJr23sBJT9qexY9PCc9o8hmT",
        "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJWdTh1RHFua3dPamQ4M0tMajZTY24yQmdGTkxGYkdSN0txX1hKSndRbm5hdHp0VVI3WElCTDdLOHVNUENJYVFtS3cxTUNWUTVhYXpOSkZrN05ha2dxQSIsImNsaWVudEV4dGVuc2lvbnMiOnt9LCJoYXNoQWxnb3JpdGhtIjoiU0hBLTI1NiIsIm9yaWdpbiI6Imh0dHBzOi8vbG9jYWxob3N0Ojg0NDMiLCJ0eXBlIjoid2ViYXV0aG4uY3JlYXRlIn0="
    }
};

3 認証とアサーション

サーバは認証をサポートするものとする(SHALL)。

サーバは認証リクエストごとにランダムなチャレンジを利用するものとする(SHALL)。チャレンジのランダム性の定義はこの仕様書の範囲外(詳細については[FIDOSecRef]を参照)ではあるが、同じチャレンジや単調増加するチャレンジ、その他単純なチャンレジを利用することは受け入れられず安全ではない。チャレンジの生成には暗号論的乱数生成器を利用することが期待される。

サーバはアサーション署名を検証するものとする(SHALL)。

アサーションレスポンスを受け取った際に、サーバは[WebAuthn]で定義されている手順でアサーションレスポンスを検証するものとする(SHALL)。

サーバはTUPおよびまたはその他ユーザ認証を検証するものとする(SHALL)。

4 コミュニケーションチャンネルの必須要件

サーバがTLSおよびトークバインディングを利用できるように実装している場合、[TokenBindingOverHttp]を利用して[TokenBindingProtocol]を実装する必要がある(SHOULD).

5 拡張機能

サーバは、拡張機能が存在しなくても登録および認証を実行できる動作モードを用意しなければならない(MUST)。ただし、本番環境にデプロイするときにそのように構築する必要があるという要件はない。

サーバは拡張機能をサポートしてもよい(MAY)。

サーバは、FIDO U2Fとの後方互換性のため、[WebAuthn]をサポートする必要がある(SHOULD)。ブラウザ、プラットフォームおよびその他クライアントが拡張機能をサポートしている可能性、サポートしていない可能性があることに注意する。

サーバが新しい拡張機能を実装した場合、[WebAuthn-Registries]レジストリに登録する必要がある(SHOULD)。

6 その他

[WebAuthn] セクション5.3.5のセキュリティ要件を遵守する必要がある。

signaturerawData属性から算出される。

サーバは、以下にRequiredと記載されたアルゴリズムを実装しなければならず(MUST)、RecommendedおよびOptionalと記載されたアルゴリズムを実装してもよい(MAY)。また、サーバはその他アルゴリズムを実装しても良い(MAY)。

名称:RS1

  • :未定(-65535の割当を要求)
  • 説明:RSASSA-PKCS1-v1_5 w/ SHA-1
  • 参照:[RFC8017] セクション8.2
  • ステータス:Required

名称:RS256

  • :未定(-257の割当を要求)
  • 説明:RSASSA-PKCS1-v1_5 w/ SHA-256
  • 参照:[RFC8017] セクション8.2
  • ステータス:Required

名称:RS384

  • :未定(-258割当を要求)
  • 説明:RSASSA-PKCS1-v1_5 w/ SHA-384
  • 参照:[RFC8017] セクション8.2
  • ステータス:Optional

名称:RS512

  • :未定(-259の割当を要求)
  • 説明:RSASSA-PKCS1-v1_5 w/ SHA-512
  • 参照:[RFC8017] セクション8.2
  • ステータス:Optional

名称:PS256

  • :-37
  • 説明:RSASSA-PSS w/ SHA-256
  • 参照:[RFC8230]
  • ステータス:Optional

名称:PS384

  • :-38
  • 説明:RSASSA-PSS w/ SHA-384
  • 参照:[RFC8230]
  • ステータス:Optional

名称:PS512

  • :-39
  • 説明:RSASSA-PSS w/ SHA-512
  • 参照:[RFC8230]
  • ステータス:Optional

名称:ES256

  • :-7
  • 説明:ECDSA using P-256 and SHA-256
  • 参照:[RFC8152]
  • ステータス:Required

名称:ES384

  • :-35
  • 説明:ECDSA using P-384 and SHA-384
  • 参照:[RFC8152]
  • ステータス:Recommended

名称:ES512

  • :-36
  • 説明:ECDSA using P-512 and SHA-512
  • 参照:[RFC8152]
  • ステータス:Optional

名称:EdDSA

  • :-8
  • 説明:EdDSA signature algorithms
  • 参照:[RFC8037]
  • ステータス:Recommended

名称:ES256K

  • :未定(-43の割当を要求)
  • 説明:ECDSA using P-256K and SHA-256
  • 参照:[SEC2V2]
  • ステータス:Optional

サーバは、以下にRequiredと記載された曲線を実装しなければならず(MUST)、RecommendedおよびOptionalと記載された曲線を実装してもよい(MAY)。また、サーバはその他の曲線を実装しても良い(MAY)。

名称:P-256

  • :1
  • 説明:EC2 NIST P-256 also known as secp256r1
  • 参照:[RFC8152]
  • ステータス:Required

名称:P-384

  • :2
  • 説明:EC2 NIST P-384 also known as secp384r1
  • 参照:[RFC8152]
  • ステータス:Recommended

名称:P-512

  • :3
  • 説明:EC2 NIST P-512 also known as secp512r1
  • 参照:[RFC8152]
  • ステータス:Optional

名称:Ed25519

  • :6
  • 説明:Edwards-curve Digital Signature Algorithm on curve 25519
  • 参照: [RFC8032]
  • ステータス:Recommended

名称:Ed448

  • :7
  • 説明:Edwards-curve Digital Signature Algorithm on curve 448
  • 参照:[RFC8032]
  • ステータス:Optional

名称:P-256K

  • :未定(8の割当を要求)
  • 説明:SECG secp256k1 curve
  • 参照:[SEC2V2]
  • ステータス:Optional

書面の都合上、この仕様書を記述している時点で実際に認証器によって利用されているアルゴリズムおよび曲線だけが、Requiredのリストに含まれている。将来の暗号論開発の可能性に先行して備えたいサーバは、必須のアルゴリズムと曲線に加え、Recommendedとなっているアルゴリズムおよび曲線を実装することを検討するべきです。

サーバはFIDOプライバシー指針 [FIDOPrivacyPrinciples]を遵守しなければなりません(MUST)。

7 トランスポートバインディングプロフィール

このセクションは非標準です。

7.1 目次

  • イントロダクション
  • 登録
    • 概要
      • Credential Creation Options
      • Authenticator Attestation Response
    • Primary IDL
      • ServerPublicKeyCredentialCreationOptionsRequest
      • ServerPublicKeyCredentialCreationOptionsResponse
      • ServerAuthenticatorAttestationResponse
    • Supporting IDL
      • ServerPublicKeyCredential
      • ServerPublicKeyCredentialUserEntity
      • ServerPublicKeyCredentialDescriptor
  • 認証
    • 概要
      • Credential Get Options
      • Authenticator Assertion Response
    • IDL
      • ServerPublicKeyCredentialGetOptionsRequest
      • ServerPublicKeyCredentialGetOptionsResponse
      • ServerAuthenticatorAssertionResponse
  • 共通
    • IDL
      • ServerResponse

7.2 イントロダクション

このドキュメントは、FIDO2サーバ向けの非標準的なREST APIを含む。このインタフェースは必須ではないが、FIDO2適合性テストツールには利用されているインタフェースであり、サーバは標準的な方法でメッセージを送受信してそれらメッセージが適合性テストツールによって検証される。

FIDO2仕様と同様に、ここで記述しているインタフェースは[WebAuthn]仕様に大きく依存している。このドキュメントの命名方法はWebAuthnに従っており、サーバと送受信するメッセージを定義するためにインタフェース定義言語(IDL)を再度利用している。

このドキュメントは、登録、認証そして共通という3つのセクションに分割されている。登録および認証のセクションではこれらの処理に関するメッセージが含まれており、共通セクションでは登録と認証の両方に共通するメッセージとデータフォーマットを含んでいる。

7.3 登録

このセクションは、クライアントとサーバ間で交換する登録メッセージの簡単な概要、それらメッセージの例とメッセージのIDL定義を記載している。WebAuthnの命名方法にしたがって「credential creation」と参照されることもあるに注意する。

7.3.1 登録の概要

登録の手順は2つのステップになっており、4種類のメッセージが送信される。最初のステップでは、クライアントが「Credential Creation Options」を受け取る。これにはクライアントがサーバに送ったServerPublicKeyCredentialCreationOptionsRequestとサーバが受け取ったServerPublicKeyCredentialCreationOptionsResponseを関連する。このはWebAuthnのnavigator.credentials.create()に利用されることを意図しており、特にサーバによって必ず生成されるチャレンジは中間者攻撃(MITM)対策のために重要である。navigator.credentials.create()の完了時に、呼び出し関数から生成されたディクショナリをServerAuthenticatorAttestationResponseresponseフィールドに設定したServerPublicKeyCredentialとしてサーバに送り返す。ServerAuthenticatorAttestationResponseは以下の共通セクションに記述している一般的なServerAuthenticatorResponseを拡張していることに注意する。サーバはチャレンジ、オリジン、署名そして[WebAuthn]仕様書のセクション7.1に記載されているアルゴリズムに従ってServerAuthenticatorAttestationResponseのその他の属性を検証し、適切なServerResponseメッセージを返却する。

7.3.2 例

7.3.2.1 例:Credential Creation Options

リクエス

  • URL:/attestation/options
  • メソッドPOST
  • URLパラメータ:なし
  • ボディapplication/jsonフォーマットのServerPublicKeyCredentialCreationOptionsRequest
    {
        "username": "johndoe@example.com",
        "displayName": "John Doe",
        "authenticatorSelection": {
            "residentKey": false,
            "authenticatorAttachment": "cross-platform",
            "userVerification": "preferred"
        },
        "attestation": "direct"
    }

成功レスポンス

    {
        "status": "ok",
        "errorMessage": "",
        "rp": {
            "name": "Example Corporation"
        },
        "user": {
            "id": "S3932ee31vKEC0JtJMIQ",
            "name": "johndoe@example.com",
            "displayName": "John Doe"
        },

        "challenge": "uhUjPNlZfvn7onwuhNdsLPkkE5Fv-lUN",
        "pubKeyCredParams": [
            {
                "type": "public-key",
                "alg": -7
            }
        ],
        "timeout": 10000,
        "excludeCredentials": [
            {
                "type": "public-key",
                "id": "opQf1WmYAa5aupUKJIQp"
            }
        ],
        "authenticatorSelection": {
            "residentKey": false,
            "authenticatorAttachment": "cross-platform",
            "userVerification": "preferred"
        },
        "attestation": "direct"
    }

エラーレスポンス

    {
        "status": "failed",
        "errorMessage": "Missing challenge field!"
    }

JavaScriptサンプル

    fetch('/attestation/options', {
        method  : 'POST',
        credentials : 'same-origin',
        headers : {
            'Content-Type' : 'application/json'
        },
        body: JSON.stringify({
            "username": "johndoe@example.com",
            "displayName": "John Doe",
            "authenticatorSelection": {
                "residentKey": false,
                "authenticatorAttachment": "cross-platform",
                "userVerification": "preferred"
            },
            "attestation": "direct"
        })
    }).then(function (response) {
        return response.json();
    }).then(function (json) {
        console.log(json);
    }).catch(function (err) {
        console.log({ 'status': 'failed', 'error': err });
    })
7.3.2.2 例:Authenticator Attestaion Response

リクエス

  • URL:/attestation/result
  • メソッドPOST
  • URLパラメータ:なし
  • ボディapplication/jsonフォーマットのServerAuthenticatorAttestationResponseresponseフィールドに設定したServerPublicKeyCredential
    {
        "id": "LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
        "rawId": "LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
        "response": {
            "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9",
            "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"
        },
        "type": "public-key"
    }

成功レスポンス

    {
        "status": "ok",
        "errorMessage": "",
    }

エラーレスポンス

    {
        "status": "failed",
        "errorMessage": "Can not validate response signature!"
    }

呼び出しサンプル

    fetch('/attestation/result', {
        method  : 'POST',
        credentials : 'same-origin',
        headers : {
            'Content-Type' : 'application/json'
        },
        body: JSON.stringify({
            "id": "LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
            "rawId": "LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
            "response": {
                "clientDataJSON": "eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9",
                "attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"
            },
            "type": "public-key"
        })
    }).then(function (response) {
        return response.json();
    }).then(function (json) {
        console.log(json);
    }).catch(function (err) {
        console.log({ 'status': 'failed', 'error': err });
    })

7.3.3 登録Primary IDL

7.3.3.1 ServerPublicKeyCredentialCreationOptionsRequest
    dictionary ServerPublicKeyCredentialCreationOptionsRequest {
        required DOMString              username;
        required DOMString              displayName;
        AuthenticatorSelectionCriteria  authenticatorSelection;
        AttestationConveyancePreference attestation = "none";
    };
  • 必須 username - エンティティについての人間が読むことができる名称。例えば「alexm」、「alex.p.mueller@example.com」や「+14255551234」
  • 必須 displayName - ユーザアカウントに対する人間にとって読みやすい名称、表示のためだけに利用されることを想定。例えば「Alex P. Müller」、「田中 倫」
  • authenticatorSelection - WebAuthn仕様書に記載されているAuthenticatorSelectionCriteriaを含むディクショナリ
  • attestation - 「none」、「indirect」「direct」を設定することができる。更なる情報はWebAuthn仕様に記載されている。デフォルトは「none」が設定される。
7.3.3.2 ServerPublicKeyCredentialCreationOptionsResponse
    dictionary ServerPublicKeyCredentialCreationOptionsResponse : ServerResponse {
        required PublicKeyCredentialRpEntity         rp;
        required ServerPublicKeyCredentialUserEntity user;

        required DOMString                                challenge;
        required sequence<PublicKeyCredentialParameters>  pubKeyCredParams;

        unsigned long                                 timeout;
        sequence<ServerPublicKeyCredentialDescriptor> excludeCredentials = [];
        AuthenticatorSelectionCriteria               authenticatorSelection;
        AttestationConveyancePreference              attestation = "none";
        AuthenticationExtensionsClientInputs         extensions;
    };
  • 必須 rp - WebAuthn仕様書に記述されているPublicKeyCredentialRpEntityとして定義されたディクショナリ
  • 必須 user - 本ドキュメントに記述したServerPublicKeyCredentialUserEntityとして定義されたディクショナリ
  • 必須 challenge - 最低16バイト長、最大64バイト長のランダムなチャレンジをbase64urlエンコードした値
  • 必須 pubKeyCredParams - WebAuthn仕様書に記述されたPublicKeyCredentialParametersの配列
  • timeout - タイムアウト(ms)
  • excludeCredentials - 本ドキュメントに記述されたServerPublicKeyCredentialDescriptorの配列
  • authenticatorSelection - WebAuthn仕様書に記述されたAuthenticatorSelectionCriteriaのセット
  • attestation - 「none」、「indirect」「direct」を設定することができる。更なる情報はWebAuthn仕様に記載されている。デフォルトは「none」が設定される。
  • extensions - WebAuthn仕様書に記述された AuthenticationExtensionsClientInputsのセット
  • このドキュメントに記載したServerResponseを拡張している
7.3.3.3 ServerAuthenticatorAttestationResponse

一般的にWebAuthnに記述されているAuthenticatorAttestationResponseと同等だが、BufferSource型のフィールドはbase64urlエンコーディングされて利用される。

dictionary ServerAuthenticatorAttestationResponse : ServerAuthenticatorResponse {
    required DOMString      clientDataJSON;
    required DOMString      attestationObject;
};
  • 必須 clientDataJSON - base64urlエンコードされたclientDataJSONバッファ
  • 必須 attestationObject - base64urlエンコードされたattestationObjectバッファ

7.3.4 登録 Supporting IDL

7.3.4.1 ServerPublicKeyCredential

一般的にWebAuthnに記述されているPublicKeyCredentialと同等だが、WebAuthnでBufferSource型のフィールドはbase64urlエンコーディングされて利用される。

dictionary ServerPublicKeyCredential : Credential {
    required DOMString                    rawId;
    required ServerAuthenticatorResponse  response;
    AuthenticationExtensionsClientOutputs getClientExtensionResults;
};
  • 必須 id - この属性はCredentialから継承しているが、ServerPublicKeyCredentialでは認証器のcredIdのbase64urlエンコードされた値にオーバーライドされている
  • 必須 rawId - idと同等
  • 必須 response - 本ドキュメントに記述したServerAuthenticatorAttestationResponseまたはServerAuthenticatorAssertionResponseによって定義されるディクショナリ
  • 必須 type - この属性はCredentialから継承しているが、ServerPublicKeyCredentialでは「public-key」にオーバーライドされている
  • getClientExtensionResult - 拡張機能の識別子を含むマップ、拡張機能のクライアント拡張処理によって生成されたクライアント拡張出力エントリが含まれる
  • Credential Management API仕様書に記述されているCredentialを拡張している
7.3.4.2 ServerPublicKeyCredentialUserEntity

一般的にWebAuthnに記述されているPublicKeyCredentialUserEntityと同等だが、idBufferSourcebase64urlエンコーディングが代わりに利用される。

    dictionary ServerPublicKeyCredentialUserEntity : PublicKeyCredentialEntity {
        required DOMString   id;
        required DOMString   displayName;
    };
  • 必須 id - base64urlエンコードされたidバッファ
  • 必須 displayName - ユーザアカウントに対する人間にとって読みやすい名称、表示のためだけに利用されることを想定。例えば「Alex P. Müller」、「田中 倫」。ServerPublicKeyCredentialCreationOptionsRequest.displayNameに対応する。
  • WebAuthn仕様書に記述されているPublicKeyCredentialEntityを拡張している
7.3.4.3 ServerPublicKeyCredentialDescription

一般的にWebAuthnに記述されているPublicKeyCredentialDescriptorと同等だが、idBufferSourcebase64urlエンコーディングが代わりに利用される。

    dictionary ServerPublicKeyCredentialDescriptor {
        required PublicKeyCredentialType      type;
        required DOMString                    id;
        sequence<AuthenticatorTransport>      transports;
    };
  • 必須 type - WebAuthn仕様書に記述されたPublicKeyCredentialTypeとして定義されたディクショナリ
  • 必須 id - 呼び出し関数に参照される公開鍵クレデンシャルのクレデンシャルIDのbase64urlエンコードされた値
  • transports - WebAuthn仕様書に記述されたAuthenticatorTransportの配列

7.4 認証

このセクションはこの認証でサーバとやり取りするメッセージの概要から始め、続いてこれらのメッセージ例について示し、メッセージの特定のIDL定義を示す。「認証」とはWebAuthnで使われている用語集に従って「クレデンシャルの取得」、「クレデンシャルリクエスト」または「認証アサーションの取得」を指すことがあることに注意する。

7.4.1 認証の概要

登録について書かれた通信フローと同様に、認証フローはサーバと交換する4つのメッセージが必要である。メッセージの最初のペアは、クライアントからサーバへのServerPublicKeyCredentialGetOptionsRequestのフォーマットのリクエストと、サーバが対応した結果としてクライアントに返却するServerPublicKeyCredentialGetOptionsResponseである。このServerPublicKeyCredentialGetOptionsResponseはWebAuthnのnavigator.credentials.get()関数のパラメータとして利用されることを想定している。navigator.credentials.get()の結果はクライアントによってresponseフィールドにServerAuthenticatorAssertionResponseを設定したServerPublicKeyCredentialに整形され、サーバに送信する。サーバは[WebAuthn]仕様書のセクション7.2に従ってアサーションを検証し、結果に応じたServerResponseを返却する。

7.4.2 認証例

7.4.2.1 認証例:Credential Get Options

リクエス

  • URL:/attestation/options
  • メソッドPOST
  • URLパラメータ:なし
  • ボティapplication/jsonエンコードされたServerPublicKeyCredentialGetOptionsRequest
    {
        "username": "johndoe@example.com",
        "userVerification": "required"
    }

成功レスポンス

{
    "status": "ok",
    "errorMessage": "",
    "challenge": "6283u0svT-YIF3pSolzkQHStwkJCaLKx",
    "timeout": 20000,
    "rpId": "https://example.com",
    "allowCredentials": [
        {
            "id": "m7xl_TkTcCe0WcXI2M-4ro9vJAuwcj4m",
            "type": "public-key"
        }
    ],
    "userVerification": "required"
}

エラーレスポンス

    {
        "status": "failed",
        "errorMessage": "User does not exists!"
    }

呼び出しサンプル

    fetch('/attestation/options', {
        method  : 'POST',
        credentials : 'same-origin',
        headers : {
            'Content-Type' : 'application/json'
        },
        body: JSON.stringify({
            "username": "johndoe@example.com",
            "userVerification": "required"
        })
    }).then(function (response) {
        return response.json();
    }).then(function (json) {
        console.log(json);
    }).catch(function (err) {
        console.log({ 'status': 'failed', 'error': err });
    })
7.4.2.2 認証例:Authenticator Assertion Response

リクエス

  • URL:/assertion/result
  • メソッドPOST
  • URLパラメータ:なし
  • ボディresponseフィールドにServerAuthenticatorAssertionResponseを設定されているapplication/jsonエンコードされたServerPublicKeyCredential
    {
        "id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
        "rawId":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
        "response":{
            "authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAAA",
            "signature":"MEYCIQCv7EqsBRtf2E4o_BjzZfBwNpP8fLjd5y6TUOLWt5l9DQIhANiYig9newAJZYTzG1i5lwP-YQk9uXFnnDaHnr2yCKXL",
            "userHandle":"",
            "clientDataJSON":"eyJjaGFsbGVuZ2UiOiJ4ZGowQ0JmWDY5MnFzQVRweTBrTmM4NTMzSmR2ZExVcHFZUDh3RFRYX1pFIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmdldCJ9"
        },
        "type":"public-key"
    }

成功レスポンス

{
    "status": "ok",
    "errorMessage": ""
}

エラーレスポンス

    {
        "status": "failed",
        "errorMessage": "Can not validate response signature!"
    }

呼び出しサンプル

    fetch('/assertion/result', {
        method  : 'POST',
        credentials : 'same-origin',
        headers : {
            'Content-Type' : 'application/json'
        },
        body: JSON.stringify({
            "id":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
            "rawId":"LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
            "response":{
                "authenticatorData":"SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAAA",
                "signature":"MEYCIQCv7EqsBRtf2E4o_BjzZfBwNpP8fLjd5y6TUOLWt5l9DQIhANiYig9newAJZYTzG1i5lwP-YQk9uXFnnDaHnr2yCKXL",
                "userHandle":"",
                "clientDataJSON":"eyJjaGFsbGVuZ2UiOiJ4ZGowQ0JmWDY5MnFzQVRweTBrTmM4NTMzSmR2ZExVcHFZUDh3RFRYX1pFIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmdldCJ9"
            },
            "type":"public-key"
        })
    }).then(function (response) {
        return response.json();
    }).then(function (json) {
        console.log(json);
    }).catch(function (err) {
        console.log({ 'status': 'failed', 'error': err });
    })

7.4.3 Authenticator IDL

7.4.3.1 ServerPublicKeyCredentialGetOptionsRequest
    dictionary ServerPublicKeyCredentialGetOptionsRequest {
        required DOMString              username;
        UserVerificationRequirement     userVerification = "preferred";
    };
  • 必須 username - エンティティについての人間が読むことができる名称。例えば「alexm」、「alex.p.mueller@example.com」や「+14255551234」
  • userVerfication - 「required」、「preferred」、「discouraged」を設定する。詳細はWebAuthn仕様書を参照する。デフォルトは「preferred」。
7.4.3.2 ServerPublicKeyCredentialGetOptionsResponse
    dictionary ServerPublicKeyCredentialGetOptionsResponse : ServerResponse {
        required DOMString                   challenge;
        unsigned long                        timeout;
        USVString                            rpId;
        sequence<ServerPublicKeyCredentialDescriptor> allowCredentials = [];
        UserVerificationRequirement          userVerification = "preferred";
        AuthenticationExtensionsClientInputs extensions;
    };
  • 必須 challenge - base64urlエンコードされたランダムなチャレンジ、チャレンジは最小でも16バイト長とし、最大は64バイト長とする
  • timeout - タイムアウト(ms)
  • rpId - このオプショナルな属性は呼び出し元が要求するリライングパーティの識別子を設定する。省略された場合、その値はCredentialsContainerオブジェクトに関連した設定オブジェクトののオリジンの有効ドメインになる
  • excludeCredentials - 本ドキュメントに記述されたServerPublicKeyCredentialDescriptorの配列
  • userVerification - 「required」、「preferred」、「discouraged」を設定する。詳細はWebAuthn仕様書を参照する。デフォルトは「preferred」。ServerPublicKeyCredentialGetOptionsRequest.userVerificationに対応した値。
  • extensions - WebAuthn仕様書に記述されているAuthenticationExtensionsClientInputsが設定されたディクショナリ
  • 本ドキュメントに記述されたServerResponseを拡張している
7.4.3.3 ServerPublicKeyCredentialDescriptor
dictionary ServerAuthenticatorAssertionResponse : ServerAuthenticatorResponse {
    required DOMString      clientDataJSON;
    required DOMString      authenticatorData;
    required DOMString      signature;
    required DOMString      userHandle;
};
  • 必須 clientDataJSON - base64urlエンコードされたclientDataJSONバッファ
  • 必須 authenticatorData- base64urlエンコードされたauthenticatorDataバッファ
  • 必須 signature- base64urlエンコードされたsignatureバッファ
  • 必須 userHandle- base64urlエンコードされたuserHandleバッファ。登録済ユーザのServerPublicKeyCredentialUserEntity.idに対応している。

7.5 共通

7.5.1 Common IDL

7.5.1.1 ServerResponse
    dictionary ServerResponse {
        required Status     status;
        required DOMString  errorMessage = "";
    }
  • 必須 status - レスポンスのステータスを示す。「ok」または「failed」のいずれかを設定できる。
  • 必須 errorMessage - statusが「failed」だった場合、このフィールは空にしてはならない(MUST NOT)。

リファレンスなどは省略した。

WebAuthnと競合する部分は少なかったと思う。バイナリ型の部分はbase64urlエンコードして送信することくらい。 追加して定義している部分としては、

  • レスポンスの基本的な形をServerResponseで定めていること、
  • サーバが実装すべき暗号アルゴリズムが指定されていること、
  • 登録・認証とどちらでもクライアントからサーバに送るリクエストが定められていること、
  • 登録でのクライアントからのリクエストに含まれるattestationフィールドに応じてサーバが値を返却すること、
  • 認証でのクライアントからのリクエストに含まれるuserVerificationフィールドに応じてサーバが値を返却すること

のはず。 この仕様書ではレスポンスの形がWebAuthnよりも定義されているので、適合性テストのためには対応しておく必要がある(【 FIDO Conformance Toolsメモ 】イントロダクション - 生き恥)。