JWT Secured Authorization Response Mode for OAuth 2.0 (JARM) メモ


## 概要

- 認可レスポンス改竄防止を目的に認可レスポンスをJWT形式で返却することを定義した仕様。

## The JWT Response Document

* JWTには以下のパラメータを含める。


| パラメータ | 説明                                |
| ---------- | ----------------------------------- |
| `iss`      | レスポンスを返却する認可サーバーURL |
| `aud`      | クライアントID                      |
| `exp`      | JWTの有効期限                       |

  

### `response_type=code`の場合の認可レスポンス

* Authorization Code Grantレスポンスの`code`(認可コード),`state`(ステート)をJWTペイロードに含める。

* 正常系レスポンスのペイロード

```json
{
  "iss":"https://accounts.example.com",
  "aud":"s6BhdRkqt3",
  "exp":1311281970,
  "code":"PyyFaux2o7Q0YfXBU32jhw.5FXSQpvr8akv9CeRDSd0QA",
  "state":"S8NJ7uqk5fY4EjNvP_G_FtyJu6pUsvH9jsYni9dMAJw"
}
```

* 異常系レスポンスのペイロード

```json
{
   "error":"access_denied",
   "state":"S8NJ7uqk5fY4EjNvP_G_FtyJu6pUsvH9jsYni9dMAJw"
}
```



### `response_type=token`の場合の認可レスポンス

* Implicit Grantレスポンスの`access_token`(アクセストークン)、`token_type`(トークン種別)、`expires_in`(有効期間)、`scope`(スコープ)、`state`(ステート)をJWTペイロードに含める。

```json
{
   "iss":"https://accounts.example.com",
   "aud":"s6BhdRkqt3",
   "exp":1311281970,
   "access_token":"2YotnFZFEjr1zCsicMWpAA",
   "state":"S8NJ7uqk5fY4EjNvP_G_FtyJu6pUsvH9jsYni9dMAJw",
   "token_type":"bearer",
   "expires_in":"3600",
   "scope":"example"
}
```

## Signing and Encryption

* **JWSで署名、もしくはJWEにて暗号化する。**

##  JWT-based Response Mode

- `response_mode`パラメータとして、認可レスポンスをJWT形式にエンコードするための値を定義する。

| `response_mode` | 説明                                                         |
| :-------------: | :----------------------------------------------------------- |
|   `query.jwt`   | URL クエリ部に認可レスポンスをJWT形式で格納して返却<br />※`response_type=token/id_token`でJWEを利用しない場合は使用しない |
| `fragment.jwt`  | URL フラグメント部に認可レスポンスをJWT形式で格納して返却    |
| `form_post.jwt` | HTTP POSTで認可レスポンスをJWT形式で格納して返却             |
|      `jwt`      | `response_type`に対応した`response_mode` でJWT形式の認可レスポンスを返却 |



### `response_mode=query.jwt`

* 認可サーバーからのHTTPリダイレクト例

```http
HTTP/1.1 302 Found
Location: https://client.example.com/cb?
response=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLm
V4YW1wbGUuY29tIiwiYXVkIjoiczZCaGRSa3F0MyIsImV4cCI6MTMxMTI4MTk3MCwiY29kZSI6IlB5eU
ZhdXgybzdRMFlmWEJVMzJqaHcuNUZYU1FwdnI4YWt2OUNlUkRTZDBRQSIsInN0YXRlIjoiUzhOSjd1cW
s1Zlk0RWpOdlBfR19GdHlKdTZwVXN2SDlqc1luaTlkTUFKdyJ9.HkdJ_TYgwBBj10C-aWuNUiA062Amq
2b0_oyuc5P0aMTQphAqC2o9WbGSkpfuHVBowlb-zJ15tBvXDIABL_t83q6ajvjtq_pqsByiRK2dLVdUw
KhW3P_9wjvI0K20gdoTNbNlP9Z41mhart4BqraIoI8e-L_EfAHfhCG_DDDv7Yg
```



### `response_mode=fragment.jwt`

* 認可サーバーからのHTTPリダイレクト例

```http
HTTP/1.1 302 Found
Location: https://client.example.com/cb#
response=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FjY291bnRzLm
V4YW1wbGUuY29tIiwiYXVkIjoiczZCaGRSa3F0MyIsImV4cCI6MTMxMTI4MTk3MCwiYWNjZXNzX3Rva2
VuIjoiMllvdG5GWkZFanIxekNzaWNNV3BBQSIsInN0YXRlIjoiUzhOSjd1cWs1Zlk0RWpOdlBfR19GdH
lKdTZwVXN2SDlqc1luaTlkTUFKdyIsInRva2VuX3R5cGUiOiJiZWFyZXIiLCJleHBpcmVzX2luIjoiMz
YwMCIsInNjb3BlIjoiZXhhbXBsZSJ9.bgHLOu2dlDjtCnvTLK7hTN_JNwoZXEBnbXQx5vd9z17v1Hyzf
Mqz00Vi002T-SWf2JEs3IVSvAe1xWLIY0TeuaiegklJx_gvB59SQIhXX2ifzRmqPoDdmJGaWZ3tnRyFW
NnEogJDqGFCo2RHtk8fXkE5IEiBD0g-tN0GS_XnxlE
```



### `response_mode=form_post.jwt`

* 認可サーバーレスポンス例

```http
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Cache-Control: no-cache, no-store
Pragma: no-cache

<html>
 <head><title>Submit This Form</title></head>
 <body onload="javascript:document.forms[0].submit()">
  <form method="post" action="https://client.example.com/cb">
    <input type="hidden" name="response"
     value="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2
      FjY291bnRzLmV4YW1wbGUuY29tIiwiYXVkIjoiczZCaGRSa3F0MyIsImV4cCI6MTM
      xMTI4MTk3MCwiYWNjZXNzX3Rva2VuIjoiMllvdG5GWkZFanIxekNzaWNNV3BBQSIs
      InN0YXRlIjoiUzhOSjd1cWs1Zlk0RWpOdlBfR19GdHlKdTZwVXN2SDlqc1luaTlkT
      UFKdyIsInRva2VuX3R5cGUiOiJiZWFyZXIiLCJleHBpcmVzX2luIjoiMzYwMCIsIn
      Njb3BlIjoiZXhhbXBsZSJ9.bgHLOu2dlDjtCnvTLK7hTN_JNwoZXEBnbXQx5vd9z1
      7v1HyzfMqz00Vi002T-SWf2JEs3IVSvAe1xWLIY0TeuaiegklJx_gvB59SQIhXX2i
      fzRmqPoDdmJGaWZ3tnRyFWNnEogJDqGFCo2RHtk8fXkE5IEiBD0g-tN0GS_XnxlE"/>
    </form>
   </body>
  </html>
```

### `response_mode=jwt`

* `response_mode=jwt&response_type=code`の場合：`query.jwt`として処理する。
* `response_mode=jwt&response_type=(token、none以外)`の場合：`fragment.jwt`として処理する。

## Processing Rules

クライアント側検証ルール

1. (任意) JWT(ヘッダ)から `kid`パラメータを取得し、対応する鍵を利用してJWTを復号する。
2. JWTから`state` パラメータを取得しユーザーエージェントとの紐付けを検証する。検証失敗時は認可処理を中断する。
3. JWTから`iss`パラメータを取得し、期待値通りか検証する。検証失敗時は認可処理を中断する。
4. JWTから`aud`パラメータを取得し、 `client_id`と一致するか検証する。検証失敗時は認可処理を中断する。
5. JWTから`exp`パラメータを取得し、有効期限内かを検証する。検証失敗時は認可処理を中断する。
6. JWTから`iss`, `kid`パラメータを取得し、その組み合わせから署名を検証する。検証失敗時は認可処理を中断する。

## Client Metadata

* クライアントが使用したいJWT の署名・暗号アルゴリズムを指定。
  * `authentication_signed_response_alg`
  * `authentication_encrypted_response_alg`
  * `authentication_encrypted_response_enc` 

## Authorization Server Metadata

* 認可サーバーがサポートするJWT の署名・暗号アルゴリズム
  * `authorization_signing_alg_values_supported` 
  * `authorization_encryption_alg_values_supported`
  * `authorization_encryption_enc_values_supported` 



## 参考情報

* [Financial-grade API: JWT Secured Authorization Response Mode for OAuth 2.0 (JARM)](https://openid.net/specs/openid-financial-api-jarm-ID1.html)