HTTP/2における証明書に基づいたリアクティブなクライアント認証 その1

20190311追記
最新仕様である Secondary Certificate Authentication in HTTP/2の解説記事を書きました
asnokaze.hatenablog.com


draft 01で大きくな変更が加えられました。証明書を要求するフローは以下より大きく変わりました。ご注意ください (2016/01/27)


HTTP/2における証明書に基づいたリアクティブなクライアント認証 その2」でdraft02について書きました(2016/05/04)


HTTP/2において、TLSハンドシェイクが完了した後に、クライアントから特定のリソースへのアクセスが有った際に追加で証明書を用いたクライアント認証を可能にする仕様が提案されています。


Reactive Certificate-Based Client Authentication in HTTP/2」 を軽く読んでみたので、簡単にメモ。(一部省略してます。間違い等あるかもしれません。)

概要

HTTPサーバは、TLSハンドシェイクが終わった後に特定のリソースにアクセスがあった時に、クライアント証明書を用いた認証を行うことができます。(リソースやユーザに依存する場合、最初のネゴシエーションに使用する証明書を決めることが出来ません。)


HTTP/1.1 + TLS1.2では、サーバからTLS HelloRequestを送ることで再ネゴシエーション(リネゴシエーション)を行い、クライント証明書を用いた認証を要求できます。しかし、HTTP/2ではこのTLSの再ネゴシエーションが禁止されています。HTTP/1.1では順番にHTTPのメッセージがやりとりされるため、クライアントは、どのHTTPリクエストがTLSネゴシエーションの契機となったかが識別可能でした。


HTTP/2ではHTTPメッセージは多重化され、その順番は決まっていません。そのためHTTP/2クライアントは、どのHTTPリクエストがTLSネゴシエーションの契機になったのか識別できません。


つまり、HTTP/2ではTLSネゴシエーションが終わった後に追加でクライアント証明書を要求し、認証(リアクティブな認証)することは出来せん。それを可能にするように、HTTP/2及びTLSを拡張する「Reactive Certificate-Based Client Authentication in HTTP/2」という仕様が提案されています。


基本的な仕組みとしては、HTTP/2でHTTPリクエストが多重化されていても、どのHTTPリクエストが再ネゴシエーション(クライアント証明書の要求)を引き起こしたのか紐付ける仕組みが導入されています。

  • HTTP/2の新しいフレームとして、「WAITING_FOR_AUTHフレーム(TBD)」が定義されています。サーバから、追加の認証が必要となったリクエストのストリーム上で、送信されます。ココにTLSレイヤのメッセージと紐付けるための識別子が含まれます。
  • TLS1.2のハンドシェイクの拡張として、application_context_idというパラメータが定義されています。TLS1.2の再ネゴシエーション中にサーバからWAITING_FOR_AUTHで送信した識別子と同じ値が設定されます。(application_context_id自体はHTTP以外でも使用可能であり、アプリケーションレイヤのコンテキスを設定するのに使用されます。)

TLS1.3では議論中ですが、同様にapplication_context_idが定義されるようです。


この識別子によって関連付けられるため、HTTP/2においてもクライアントはどのリクエストがクライアント証明書の要求がされているのか識別することが出来るようになります。


この仕様中では、TLS1.2及びTLS1.3のそれぞれでリアクティブなクライアント認証の手順を定義していますが、TLS1.3のクライアント認証の手順は議論されている段階な点に注意が必要です。

HTTP/1.1におけるリアクティブな証明書を用いたクライアント認証

まず、HTTP/1.1での、TLSネゴシエーションが終わった後の追加の認証手順を確認します。

HTTP/1.1 + TLS1.2

TLS1.2の例は以下のとおりです。TLSネゴシエーションという形でクライント証明書を用いた認証が行われます。簡単な例を以下に示します。

  • 1. サーバは保護されたりソースへのリクエストを受信する
  • 2. 認証確認を行い、サーバはクライアント証明書を用いた認証を要求をする。サーバはTLS HelloRequestを送信することでTLSネゴシエーションを開始する。(いくつかのメッセージは簡潔にするために省略されています)
  • 3. この例の重要なメッセージは、サーバが証明書を要求しているTLS CertificateRequestです。
  • 4. クライアントはCertificateとCertificateVerifyメッセージで、証明書と鍵を所有することの証明を提供します
  • 5. ハンドシェイクが完了すると、有効なクライアント証明書により、リクエストは認証されリソースが提供されます。
HTTP/1.1 + TLS1.3

TLS 1.3では、ハンドシェイクが完了した後にクライアントを認証する、新しいクライアント認証の仕組みが導入されます。
HTTPリクエストを認証する目的で、これは機能的に再ネゴシエーションすることと等価です。簡単に以下に例をしめします。



TLS1.3では再ネゴシエーションをサポートしておらず、かわりに直接的にクライアント認証を要求できます。TLS1.2とは対照的に、TLS1.3では簡潔にクライアント証明書を要求できます。

HTTP/2 + TLS1.3

TLS1.3を使用してHTTP/2通信を行っていれ場合の説明をします。


リアクティブなクライアント証明書認証をサポートするHTTP/2クライアントからのリクエストによって、追加のクライアント認証が要求されます。
TLS1.3では、サーバはTLS CertificateRequestメッセージを送信することでこれを行います。


サーバはまず最初に、クライアントのクレデンシャルを要求することとなったストリーム上でWAITING_FOR_AUTHフレームを送信する必要があります(MUST)。サーバによって、TLS CertificateRequestのcertificate_request_id (name TBD) フィールドはWAITING_FOR_AUTHフレームの値と同じ値が設定されます。


サーバは、複数のストリームで同じ値を持つWAITING_FOR_AUTHフレームを送信することも出来ます。また、複数のTLS CertificateRequestを送ったり、一つのストリーム上で複数のWAITING_FOR_AUTHフレームを順次送ることも出来ます。

HTTP/2 + TLS1.2

TLS1.2を使用してHTTP/2通信をしている場合の説明をします。また、合わせてTLS1.2に対する拡張である「TLS application_context_id Hello Extension」も合わせて説明します。


TLS1.2を使用するHTTP/2サーバは、HTTP/2 WAITING_FOR_AUTHフレームを送信して、続いてTLS HelloRequestを送信し、クライアント認証を開始します。これにより、TLSネゴシエーションが開始されます。


TLS HelloRequestメッセージを受け取ったHTTP/2クライアントは、空のapplication_context_idを含んだTLSハンドシェイクを開始しなければなりません。クライアントは再ネゴシエーションをサポートしていなければ、TLS no_renegotiationアラートを送信しなければならない(MUST)。


サーバは、以前にWAITING_FOR_AUTHフレームで送信した値と同じ値を持つ「application_context_id」を設定します。


TLS1.3同様、サーバは、ひとつのリクエストに対しても複数のリクエストに対しても、複数のクライアント証明書を要求できます。同時には一つのリネゴシエーションのみが処理可能です。リネゴシエーションが完了すると、HelloRequestを送信することが出来ます。サーバは一つのコネクション上で提出されたクライアント証明書を累積して扱う事ができ、複数の証明書が提出されたとして扱うことが出来ます。

TLS application_context_id Hello Extension

TLS Hello Extensionのapplication_context_id はTLSハンドシェイク中でアプリケーションからコンテキストを伝達するのに使用されます。これは、TLSハンドシェイクを開始する原因となったアプリケーションコンテキストを識別するのに使用されます。このフィールドのセマンティクスはアプリケーションに依存し、さらにはアプリケーションの状態にも依存しえます。


HTTPでは/2クライアントは常に空の値を「application_context_id」を提供し、サーバは常に、その後のWAITING_FOR_AUTHフレームに表示される値を提供します。

HTTP/2における再ネゴシエーションの許可

HTTP/2(RFC7540)では、TLSネゴシエーションが禁止されていますが、以下の条件が守られている場合はその制限は解除されます。

これらの条件が守られない場合は、各種エラー(アラート)を送信することになります。

リアクティブな証明書認証のサポートの通知

リアクティブな証明書認証をサポートしているHTTP/2クライアントは、サポートしていることを「SETTINGS_REACTIVE_AUTH」パラメータを使用して通知できます。
デフォルト値は、サポートしていないことを示す「0」が設定されます。サポートしている場合は「1」を設定します。それ以外の値が設定されている場合はエラーとなります。