JSON Web Token(JWT) 概要

JSON Web Token(JWT)の概要記事。

## JWTとは

* JSON Web Tokenの略称。
* 属性情報(`Claim`)をJSONデータ構造で表現したトークン仕様を指す。


## JWTの構造

以下の例を用いて説明する。

```
eyJ0eXAiOiJKV1QiLA0KICJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
```

* `.`で区切られたフィールドから構成される。

* `<ヘッダー(Header)部>.<ペイロード(Payload)部>.<署名(Signature)部>`

  * 上記を**JSON Web Signature (JWS)**形式と呼ぶ。

  * ５つのフィールドを持つ形式は、**JSON Web Encryption** (**JWE**)と呼ぶ。
 
    ```
    ヘッダー.キー.初期ベクター.暗号文.認証タグ
    ```

![JWT_Structure.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/3d129f01-2e04-6ffd-6688-304f8e6a3fb7.png)

### ヘッダー部

* 署名検証に必要な情報を格納する。

* JSONをBase64URLエンコードした文字列。

* 上述の例は、以下のJSONをエンコードしている。

  ```json
  {
       "typ":"JWT",
       "alg":"HS256"
  }
  ```

  * `typ`:JWT形式の文字列であることを表す。
  * `alg`:署名アルゴリズムを表す。

### ペイロード部

* ペイロード:アプリ間のやりとりに必要な属性情報（`Claim`）

    * 事前定義されたクレーム※詳細はRFC参照

| クレーム名 | 説明                                                         |
| :--------- | :----------------------------------------------------------- |
| `iss`      | 発行者 (issuer) を識別するための識別子。文字列 or URIを指定。 |
| `sub`      | ユーザーの識別子。データベース内のユーザーテーブルのプライマリーキーが指定されることが多い。 |
| `aud`      | JWT の受け取り手の識別子。発行を依頼したクライアントIDなど。 |
| `exp`      | JWT の有効期限。                                             |
| `nbf`      | JWTが有効になる日時。                                        |
| `iat`      | JWTの発行日時。                                              |
| `jti`      | JWTのユニーク性を保証する識別子。                            |

* `Claim`をJSON形式で表現し、Base64urlエンコードした文字列。上記の例は、以下のJSONをエンコードしている。

  ```json
  {
    "iss": "joe",
    "exp": 1300819380,
    "http://example.com/is_root": true
  }
  ```

### 署名部

* エンコードされたヘッダー、ピリオド（`.`）、エンコードされたペイロードを連結した値を入力として`alg`の署名アルゴリズムで署名し、Base64urlエンコードすることで作成した値。

* 上記の例の場合、以下の値となる。

  ```
  dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
  ```



## JWT活用事例

### OAuth 2.0 Client Authentication and Authorization Grants

#### Authorization Grants

* アクセストークンのリクエストに利用する。

  ```HTTP
  POST /token.oauth2 HTTP/1.1
  Host: as.example.com
  Content-Type: application/x-www-form-urlencoded
  
  grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&
　assertion=eyJhbGciOiJFUzI1NiIsImtpZCI6IjE2In0.eyJpc3Mi[...omitted for brevity...].J9l-ZhwP[...omitted for brevity...]
  ```

  * `grat_type`:`urn:ietf:params:oauth:grant-type:jwt-bearer`を指定する。
  * `assertion`:JWTを指定する。

#### Client Authentication

* クライアント認証を行う際、ID/シークレットの代わりに利用する。

  ```http
  POST /token.oauth2 HTTP/1.1
  Host: as.example.com
  Content-Type: application/x-www-form-urlencoded
  
  grant_type=authorization_code&
  code=n0esc3NRze7LTCu7iYzS6a5acc3f0ogp4&
  client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&
  client_assertion=eyJhbGciOiJSUzI1NiIsImtpZCI6IjIyIn0.eyJpc3Mi[...omitted for brevity...].cC4hiUPo[...omitted for brevity...]
  ```

  * `client_assertion_type`:`urn:ietf:params:oauth:client-assertion-type:jwt-bearer`を指定する。
  * `client_assertion`:JWTを指定する。

### Open ID Connect ID Token

* ユーザーの認証結果として発行するトークン
  * ユーザー認証、ユーザー属性に関する`Claim`を格納する。

    

## 参考情報

* [JSON Web Token(JWT)](https://tools.ietf.org/html/rfc7519)
* [JSON Web Token（JWT）の紹介とYahoo! JAPANにおけるJWTの活用](https://techblog.yahoo.co.jp/advent-calendar-2017/jwt/)
* [IDトークンが分かれば OpenID Connect が分かる](https://qiita.com/TakahikoKawasaki/items/8f0e422c7edd2d220e06#61-jws-%E5%BD%A2%E5%BC%8F%E3%81%AE-jwt)