client_secret_jwt によるクライアント認証

概要


本ドキュメントでは client_secret_jwt によるクライアント認証 (OpenID Connect Core 1.0, 9. Client Authentication) とその利用方法について解説します。


client_secret_jwt


認可サーバーが client_secret_jwt によってクライアントを認証する場合、クライアントはトークンエンドポイントへのリクエストに assertion (JWT) と呼ばれる認証情報を含める必要があります。 assertion として送信する JWT には署名・ペイロードに関していくつかの要件が定められており、認可サーバー側ではこの検証を行う必要があります。具体的に必要となる処理はそれぞれ下記の通りとなります。

クライアント側の処理


トークンエンドポイントにおいて client_secret_jwt によるクライアント認証が要求される場合、クライアントはトークンリクエストに以下のパラメーターを含める必要があります。
パラメーター
説明
client_assertion_type
client_assertion のタイプ
client_assertion
クライアントの認証情報を含む JWT

client_assertion_type には "urn:ietf:params:oauth:client-assertion-type:jwt-bearer" という文字列を指定する必要があります。

client_assertion にはクライアントの認証情報を含んだ JWT を指定する必要があります。具体的には以下の要件を満たす JWT を指定します。

<署名>
  • 署名は HMAC SHA のアルゴリズム  (HS256 など) を用いて計算すること
  • 署名計算時にはクライアントシークレットを共通鍵として利用すること

<ペイロード>
下記のうち、必須のクレイムを含めること。
クレイム
必須
説明
iss
YES
この JWT の発行者。値はクライアント ID に一致しなければならない。
sub
YES
この JWT のサブジェクト。値はクライアント ID に一致しなければならない。
aud
YES
この JWT の受け取り手。認可サーバーはこの値が適切なものかどうか検証しなければならない。また、この値はトークンエンドポイントの URI であるべきである。
jti
YES
この JWT の ID
exp
YES
この JWT の有効期限
iat
NO
この JWT の発行日時

上記要件を満たす JWT の具体例は、下記「assertion の生成」のセクションをご覧ください。

サーバー側の処理


認可サーバー側では、リクエストを下記仕様に従って適切に処理することになります。


これらの処理は全て Authlete に委譲できるため、ここでは詳細は割愛します。

Authlete 上で必要な設定


Authlete において client_secret_jwt によるクライアント認証を行うためには以下の設定が必要になります。

サービスの設定


以下のように設定してください。
設定対象項目
設定内容
サポートするクライアント認証方式
少なくとも CLIENT_SECRET_JWT を含めるようにする

クライアントの設定


以下のように設定してください。
設定対象項目
設定内容
クライアントタイプ
Confidential
アサーション署名アルゴリズム
以下のいずれかの値。

HS256, HS384, HS512

実行例


以下では、認可サーバーのトークンエンドポイントにおいて client_secret_jwt によるクライアント認証を行うケースをシミュレートします。

assertion の生成


事前準備として、トークンリクエストに含める client_assertion パラメーターの値 (JWT) を生成します。

まず JWT 内のペイロードとして以下のような JSON ファイルを生成してください。ここでは payload.json というファイル名でこれを保存します。

{
                                                  "jti":"<この JWT の ID>",
                                                  "sub":"<クライアント ID>",
                                                  "iss":"<クライアント ID>",
                                                  "aud":"<認可サーバーのトークンエンドポイントの URL>",
                                                  "exp":<この JWT の有効期限>,
                                                  "iat":<この JWT が発行されたタイムスタンプ>
                                                }

具体的には以下のようになります。

{
                                                  "jti":"myJWTId001",
                                                  "sub":"38174623762",
                                                  "iss":"38174623762",
                                                  "aud":"http://localhost:4000/api/auth/token/direct/24523138205",
                                                  "exp":1536165540,
                                                  "iat":1536132708
                                                }

続いて、このペイロードを含む JWT を生成します。
以下は authlete-jose ライブラリを利用して JWT を生成する例になります。

$ bin/jose-generator \
                                                --payload-file payload.json \
                                                --sign \
                                                --signing-alg HS256 \
                                                --signing-alg-key TzPTZDtcw9ek41H1VmofRoXQddP5cWCXPWidZHSA2spU6gZN9eIFUiXaHD7OfxtBhTxJsg_I1tdFI_CkKl8t8Q

結果的に以下のような JWT が得られます。(見やすさを考慮し一部改行してあります。)

eyJhbGciOiJIUzI1NiJ9.
                                                ewogICJqdGkiOiJteUpXVElkMDAxIiwKICAic3ViIjoiMzgxNzQ2MjM3NjIiLAogICJpc3MiOiIzODE3NDYyMzc2MiIsCiAgImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMC9hcGkvYXV0aC90b2tlbi9kaXJlY3QvMjQ1MjMxMzgyMDUiLAogICJleHAiOjE1MzYxNjU1NDAsCiAgImlhdCI6MTUzNjEzMjcwOAp9Cg.
                                                Vin3IxRPMLQ0SKNJ8Ba_59dYHBGLb4Ft-JLbJVKFd3E

トークンリクエストのシミュレート


クライアントから認可サーバーに対して以下のトークンリクエストが投げられたと仮定します。(見やすさを考慮し一部改行してあります。)

POST /token.oauth2 HTTP/1.1
                                                Host: as.example.com
                                                Content-Type: application/x-www-form-urlencoded
                                              
                                                grant_type=authorization_code&
                                                code=Gw30fMKJBHkcOBSde5awLrMm4ahvgCNM2cFSTUOUflY&
                                                redirect_uri=https://example.com/redirection
                                                client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
                                                client_assertion=eyJhbGciOiJIUzI1NiJ9.
                                                                 ewogICJqdGkiOiJteUpXVElkMDAxIiwKICAic3ViIjoiMzgxNzQ2MjM3NjIiLAogICJpc3MiOiIzODE3NDYyMzc2MiIsCiAgImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMC9hcGkvYXV0aC90b2tlbi9kaXJlY3QvMjQ1MjMxMzgyMDUiLAogICJleHAiOjE1MzYxNjU1NDAsCiAgImlhdCI6MTUzNjEzMjcwOAp9Cg.
                                                                 Vin3IxRPMLQ0SKNJ8Ba_59dYHBGLb4Ft-JLbJVKFd3E

これを受けた認可サーバーは Authlete の /api/auth/token API に対してリクエストを投げます。以下のコマンドはこれをシミュレートしています。

$ curl -v -X POST https://api.authlete.com/api/auth/token \
                                                -H 'Content-Type: application/json' \
                                                -u '10629969330:tszcLrddM8146JPApzflvRYc7QVU3HhkwCQnoAWF3UI' \
                                                -d '{ 
                                                       "parameters":"grant_type=authorization_code&
                                                                     code=Gw30fMKJBHkcOBSde5awLrMm4ahvgCNM2cFSTUOUflY&
                                                                     redirect_uri=https://example.com/redirection&
                                                                     client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&
                                                                     client_assertion=eyJhbGciOiJIUzI1NiJ9.
                                                                                      ewogICJqdGkiOiJteUpXVElkMDAxIiwKICAic3ViIjoiMzgxNzQ2MjM3NjIiLAogICJpc3MiOiIzODE3NDYyMzc2MiIsCiAgImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3Q6NDAwMC9hcGkvYXV0aC90b2tlbi9kaXJlY3QvMjQ1MjMxMzgyMDUiLAogICJleHAiOjE1MzYxNjU1NDAsCiAgImlhdCI6MTUzNjEzMjcwOAp9Cg.
                                                                                      Vin3IxRPMLQ0SKNJ8Ba_59dYHBGLb4Ft-JLbJVKFd3E"
                                                    }'

上記リクエストが正常に処理されると以下のようなレスポンスが得られます。

{
                                                    "type":"tokenResponse",
                                                    "resultCode":"A050001",
                                                    "resultMessage":"[A050001] The token request (grant_type=authorization_code) was processed successfully.",
                                                    "accessToken":"kwXY57oN4nBOqxk57vW2fo-WzgezrwSl2h1N_xW8aKI",
                                                    ...
                                                }

How did we do with this article?