はじめに
この記事では、OAuth 2.0 の『クライアント認証』について説明します。
RFC 6749 に記述されているクライアント認証方式のほか、クライアントアサーションやクライアント証明書を用いるクライアント認証方式についても説明します。
1. クライアント認証方式
1.1. トークンエンドポイント
認可サーバーからアクセストークンの発行を受けたいクライアントアプリケーションがあります。
アクセストークンは、幾つかの例外を除き、認可サーバーのトークンエンドポイントから発行されます。そのため、認可サーバーはトークンエンドポイントを用意します。
クライアントアプリケーションは、アクセストークンの発行を受けるために、トークンエンドポイントにトークンリクエストを投げます。
認可サーバーは、トークンレスポンスを返します。この応答の中に、アクセストークンが含まれます。
1.2. クライアントタイプ
クライアントアプリケーションには、クライアントタイプ(RFC 6749, 2.1. Client Types)という属性があります。
この属性の値は、public(パブリック)もしくは confidential(コンフィデンシャル)のどちらかです。
クライアント認証という手続きが必要になります。これは、クライアントの身元を確認するための処理です。
1.3. client_secret_post
昔ながらのクライアント認証の方法では、まず、当該クライアントアプリケーション用のクライアント ID とクライアントシークレットを認可サーバーが生成し、あらかじめクライアントアプリケーションに渡しておきます。
クライアントアプリケーションは、トークンリクエストを投げる際、
トークンリクエストにクライアント ID とクライアントシークレットを含めます。認可サーバーは、トークンリクエストに含まれるクライアント ID とクライアントシークレットをチェックすることで、クライアントの身元を確認することができます。
トークンリクエストにクライアント ID とクライアントシークレットを含める方法で一番分かりやすい方法は、client_id
および client_secret
というリクエストパラメーターを使う方法です。
このクライアント認証方式には client_secret_post
という名前が与えられています(OIDC Core, 9. Client Authentication)。
1.4. client_secret_basic
トークンリクエストにクライアント ID とクライアントシークレットを含めるもう一つの方法は、ベーシック認証(RFC 7617)を使う方法です。
この方法を使う場合、まず、クライアント ID、コロン、クライアントシークレットを連結し、一つの文字列を作ります。
次に、この文字列を BASE64(RFC 4648)でエンコードします。
そして、出来上がった BASE64 文字列を、トークンリクエストの Authorization
ヘッダーに埋め込みます。
このクライアント認証方式には client_secret_basic
という名前が与えられています(OIDC Core, 9. Client Authentication)。
client_secret_post
と client_secret_basic
は、RFC 6749, 2.3.1. Client Password に書かれているクライアント認証方式です。
1.5. client_secret_jwt
クライアントシークレットを直接トークンリクエストに含めずとも、クライアントシークレットを持っていることを間接的に証明する方法があります。
次に、クライアントシークレットを用いてそのデータに対する署名を生成します。
認可サーバーは、その署名を検証することで、トークンリクエストを投げてきたクライアントアプリケーションがクライアントシークレットを持っていることを確認でき、もってクライアント認証とすることができます。
ここで用意するデータの形式にはルールがあります。詳細は RFC 7523, 2.2. Using JWTs for Client Authentication に書かれています。簡単に言うと、iss
クレームなどを含む JSON です。
この JSON に対する署名は、RFC 7515(JSON Web Signature)に定義されている方法でおこないます。署名の結果、JWT(RFC 7519)が生成されますが、この JWT は、クライアント認証の文脈ではクライアントアサーションと呼ばれます。
そして、このクライアントアサーションを client_assertion
リクエストパラメーターの値としてトークンリクエストに含めます。また、同時に、client_assertion_type
リクエストパラメーターも追加します。client_assertion_type
の値は、urn:ietf:params:oauth:client-assertion-type:jwt-bearer
という固定値です。
このクライアント認証方式には client_secret_jwt
という名前が与えられています(OIDC Core, 9. Client Authentication)。
1.6. private_key_jwt
前節のクライアント認証方式では、クライアントアサーションの署名を生成する際、クライアントシークレットという共有鍵を用いました。一方、クライアントアサーションの署名と検証に非対称鍵を用いる方法もあります。
そして、何らかの方法で、認可サーバーが公開鍵を参照できるようにしておきます。
トークンリクエストに先立って、クライアントは、RFC 7523, 2.2. Using JWTs for Client Authentication の仕様に従って JSON データを用意します。
生成されたクライアントアサーションを client_assertion
リクエストパラメーターの値とし、トークンリクエストをおこないます。
認可サーバーは、トークンリクエストの中からクライアントアサーションを取り出します。
そして、公開鍵を用いてクライアントアサーションの署名検証をおこないます。
このクライアント認証方式には private_key_jwt
という名前が与えられています(OIDC Core, 9. Client Authentication)。
1.7. tls_client_auth
OAuth 2.0 Mutual TLS Client Authentication and Certificate-Bound Access Tokens(以降 MTLS)という仕様があります。この仕様の「2. Mutual TLS for OAuth Client Authentication」には、クライアント証明書を用いるクライアント認証方式が定義されています。
MTLS で定義されているクライアント認証方式を用いるためには、まず、クライアントアプリケーションとトークンエンドポイントの間の接続が、Mutual TLS でなければなりません。
通常の TLS では、サーバー側のみ証明書の提示をおこないますが、Mutual TLS では、クライアント側も自身の証明書を提示します。この結果、サーバー側にクライアント証明書が渡ってきます。
サーバーは、そのクライアント証明書をクライアント認証に用います。
クライアント証明書として PKI 証明書を用いる場合、クライアントは、その証明書の主体を識別するための情報を事前にサーバーに登録しておかなければなりません。主体を識別する情報は、次のいずれかです。
識別情報 | クライアントメタデータ名 |
---|---|
Subject Distinguished Name | tls_client_auth_subject_dn |
Subject Alternative Name, DNS | tls_client_auth_san_dns |
Subject Alternative Name, URI | tls_client_auth_san_uri |
Subject Alternative Name, IP address | tls_client_auth_san_ip |
Subject Alternative Name, Email | tls_client_auth_san_email |
サーバーは、受け取ったクライアント証明書の主体識別情報が事前登録されているものと一致することを確認し、もってクライアント認証とします。
このクライアント認証方式には tls_client_auth
という名前が与えられています(MTLS, 2.1.1. PKI Method Metadata Value)。
なお、クライアント証明書には OAuth 2.0 の文脈におけるクライアント ID は入っていないので、クライアント証明書だけではクライアントを特定することはできません。そのため、クライアント証明書を用いるクライアント認証をおこなう際は、別途クライアント ID をリクエストに含める必要があります。通常は client_id
リクエストパラメーターが使用されます。
1.8. self_signed_tls_client_auth
クライアント証明書を用いるクライアント認証において、PKI 証明書ではなく、自己署名証明書を用いる場合もあります。自己署名証明書を用いる場合、クライアントは、証明書を事前にサーバーに登録しておかなければなりません。
このクライアント認証方式には self_signed_tls_client_auth
という名前が与えられています(MTLS, 2.2.1. Self-Signed Method Metadata Value)。
2. メタデータ
クライアント認証方式に関連するメタデータを紹介します。
2.1. サーバーメタデータ
2.1.1. token_endpoint_auth_methods_supported
トークンエンドポイントでサポートするクライアント認証方式です。client_secret_basic
や private_key_jwt
などの値を持つ配列です。
2.1.2. token_endpoint_auth_signing_alg_values_supported
トークンエンドポイントにおいてクライアントアサーションによるクライアント認証をおこなう際、クライアントアサーションの署名で使用可能なアルゴリズムです。HS256
や ES256
など、RFC 7518(JSON Web Algorithms)の 3.1. "alg" (Algorithm) Header Parameter Values for JWS に列挙されている値を持つ配列です。
2.1.3. revocation_endpoint_auth_methods_supported
リボケーションエンドポイント(RFC 7009)でサポートするクライアント認証方式です。内容は token_endpoint_auth_methods_supported
と同じです。
2.1.4 revocation_endpoint_auth_signing_alg_values_supported
リボケーションエンドポイント(RFC 7009)においてクライアントアサーションによるクライアント認証をおこなう際、クライアントアサーションの署名で使用可能なアルゴリズムです。内容は token_endpoint_auth_signing_alg_values_supported
と同じです。
2.1.5. introspection_endpoint_auth_methods_supported
イントロスペクションエンドポイント(RFC 7662)でサポートするクライアント認証方式です。内容は token_endpoint_auth_methods_supported
と同じです。
2.1.6. introspection_endpoint_auth_signing_alg_values_supported
イントロスペクションエンドポイント(RFC 7662)においてクライアントアサーションによるクライアント認証をおこなう際、クライアントアサーションの署名で使用可能なアルゴリズムです。内容は token_endpoint_auth_signing_alg_values_supported
と同じです。
2.1.7. バックチャネル認証エンドポイント関連
CIBA Core で定義される**バックチャネル認証エンドポイント**は、仕様上、confidential クライアントしか利用できないことになっており、利用する際には必ずクライアント認証が必要となります。
参考:CIBA PING モードによるアクセストークン発行フロー |
認可サーバーのメタデータを列挙している RFC 8141 では、トークンエンドポイント、リボケーションエンドポイント、イントロスペクションエンドポイント毎にそれぞれ、サポートするクライアント認証方式(*_endpoint_auth_methods_supported
)とサポートするクライアントアサーション署名アルゴリズム(*_endpoint_auth_signing_alg_values_supported
)を表すメタデータが用意されています。そのため、CIBA Core 仕様策定中、バックチャネル認証エンドポイント用にもメタデータを新しく定義してはどうかと提案しました(【Issue 102】CIBA: Metadata for client auth at backchannel endpoint)。
しかしながら、最終的には、バックチャネル認証エンドポイント用に新しくメタデータを定義はせず、トークンエンドポイント用のメタデータで代用することとなりました。そもそも論として、エンドポイント毎にクライアント認証関連のメタデータを定義してきたこれまでの慣習が良くない、という話になりました。この議論については、「世界最先端の認証認可技術、実装者による『CIBA』解説」の「3.2. クライアント認証」をご参照ください。
2.1.8. デバイス認可エンドポイント関連
RFC 8628(OAuth 2.0 Device Authorization Grant)、いわゆるデバイスフローでは、新たにデバイス認可エンドポイントが定義されます。クライアントが confidential クライアントの場合、他のエンドポイントと同様、デバイス認可エンドポイントにアクセスする際にクライアント認証が要求されます。
参考:デバイスフローと Authlete API |
ただし、仕様書には、デバイス認可エンドポイントがサポートするクライアント認証方式を表すメタデータについて言及がありません。そこで、「デバイス認可エンドポイントにおけるクライアント認証方式に関する記述を仕様書に追加する予定があるか」という問いを OAuth メーリングリストに投げてみました([OAUTH-WG] Client Authentication Method at Device Authorization Endpoint)。
しかしながら、今までのところ、メタデータの扱いに関する議論に進捗はありません。デバイスフローについては公式テストも存在しないので、デバイス認可エンドポイントのクライアント認証方式の厳密な動作について気にする人もそれほどいないのでしょう。やむなく Authlete の実装では、CIBA に倣い、トークンエンドポイントのメタデータで代用することにしています。
2.2. クライアントメタデータ
2.2.1. token_endpoint_auth_method
クライアントがトークンエンドポイントで使用するクライアント認証方式です。client_secret_basic
や private_key_jwt
などを指定します。クライアントタイプが public の場合はクライアント認証をおこなわないので、none
を指定します。
2.2.2. token_endpoint_auth_signing_alg
クライアントがトークエンドポイントでクライアントアサーションを用いたクライアント認証をおこなう際、クライアントアサーションの署名に使うアルゴリズムです。RFC 7518(JSON Web Algorithms)の 3.1. "alg" (Algorithm) Header Parameter Values for JWS に列挙されている値のいずれかを指定します。
クライアント認証方式に client_secret_jwt
を選んでいる場合は、署名アルゴリズムは対称鍵系である HS256
、HS384
、HS512
のいずれかになります。ただし、認可サーバーにより発行されたクライアントシークレットのエントロピーよりも高いビット数のアルゴリズムを選んでも、あまり益はないので注意してください。
一方、クライアント認証方式に private_key_jwt
を選んでいる場合は、署名アルゴリズムに ES256
などの非対称鍵系アルゴリズムを設定することになります。
3. Financial-grade API による要求事項
3.1. クライアント認証方式
従来の OAuth 2.0 や OpenID Connect よりも高いセキュリティーを要求する Financial-grade API(FAPI)では、使用可能なクライアント認証方式に制限をかけています。
RFC 6749 に記述されている昔ながらのクライアント認証方式(client_secret_basic
と client_secret_post
)は、使用してはいけないことになっています。
Read-Only API 用のセキュリティープロファイルである FAPI Part 1 では、使用可能はクライアント認証方式は次の 4 つです。
client_secret_jwt
private_key_jwt
tls_client_auth
self_signed_tls_client_auth
Read-and-Write API 用のセキュリティープロファイルである FAPI Part 2 では、client_secret_jwt
が使用不可となり、次の 3 つのクライアント認証方式のみが許されます。
private_key_jwt
tls_client_auth
self_signed_tls_client_auth
3.2. クライアントアサーション署名アルゴリズム
FAPI Part 2 の「8.6. JWS algorithm considerations」では、JWS の署名アルゴリズムに制限をかけています。Read-and-Write API の文脈では、ES256
と PS256
以外のアルゴリズムを使用してはいけないことになっています。
この要求事項は、クライアントアサーションを用いるクライアント認証方式に影響を与えます。
3.3. キーサイズ
FAPI Part 1 の「5.2.2. Authorization Server」の 5 番目の規定により、クライアント認証で RSA 系アルゴリズムが用いられる場合、鍵のサイズは 2048 ビット以上でなければなりません。また、6 番目の規定により、楕円曲線系のアルゴリズムが用いられる場合、鍵のサイズは 160 ビット以上でなければなりません。
4. Authlete
Authlete(オースリート)は、
この記事で紹介したクライアント認証方式を全てサポートしています。
クライアントアサーション署名アルゴリズムも全てサポートしています。
クライアント証明書系(MTLS)とクライアントアサーション系(Private Key)の双方のカテゴリーで公式 FAPI 認証を取得している、(サンドボックスではなく)商用環境で利用可能な、世界で唯一の実装です(2019 年 7 月 14 日現在)。
さいごに
いろいろなサービスが API として提供されるようになり、便利な世の中になってきました。しかし、その一方で、不適切な実装のせいで、セキュリティー問題も頻発するようになってしまいました。
API 公開にあたってセキュリティーを重視されたい場合は、Financial-grade API の実装として公式認証を取得している Authlete の利用をご検討ください。お問い合わせは、Authlete 社のお問合せページ、または sales@authlete.com までご連絡ください。よろしくお願い致します。