JSON Web Token (JWT) の 仕様 と 使い方

0 件のコメント

今回は「JSON Web Token」についてまとめます。

概要

JSON Web Token は略して JWT (ジョット) と呼びます。

「セッション情報をサーバーサイドで保存せずクライアントサイドで保持できる(ステートレスが実現できる)」点が特徴です。 WebAPIとか作るときは便利な仕様です。

JWTの仕様(= トークンの仕様)自体はシンプルですし、使い方も簡単です。 ただ…使い方を間違えると脆弱性ができてしまうので、使い方には要注意です。

仕様

JWTはその名に「トークン」が付く通り「トークン」の構造が重要になります。 ここではそのトークン構造がどうなっているのか詳細を見ていきます。

JWTに定義されるトークン構造は以下のようになっています。

token = base64UrlEncode(header) + "." +
        base64UrlEncode(payload) + "." +
        base64UrlEncode(signature)

構成要素は以下の3要素+1エンコードです。各要素をエンコードしたものを .(ピリオド) で結合したものがトークンになります。

  • ヘッダー
  • ペイロード
  • 署名
  • Base64URLエンコード

ヘッダーには「署名アルゴリズム」、ペイロードには「保存したいデータ」、署名には「トークンが改ざんされていないか確認するための署名」を入れます。

Base64URLエンコード は Base64エンコードとやや異なります。 Base64URLエンコードは「Base64 エンコード したとき出現する URLアンセーフ な文字( +/ )を URLセーフな文字( -_ )に置き換え、パディング( = )を入れないURLセーフなエンコード方式」になります。

「署名で利用するアルゴリズム」と「このトークンが何ものか」を指定します。

{
  "typ": "JWT",
  "alg": "ES256"
}
項目 名称 説明
typ Type 任意項目。 JWT 固定で指定。
alg Algorithm 署名に利用するアルゴリズムを指定。 指定できるアルゴリズムはRS256, ES256, none など。 脆弱性の観点(公開鍵暗号方式が良い)から HSxxxnone 以外がおススメ。 指定できる値の詳細は別表(algに指定できる値)参照。

algに指定できる値

algに指定できるアルゴリズムの一覧は以下の通り。 指定できる値については RSC7518 - JSON Web Algorithms (JWA) もしくは JSON Object Signing and Encryption (JOSE) に記載があります。

アルゴリズム 暗号鍵
HS256 HMAC using SHA-256 共通鍵
HS384 HMAC using SHA-384 共通鍵
HS512 HMAC using SHA-512 共通鍵
RS256 RSASSA-PKCS1-v1_5 using SHA-256 秘密鍵
RS384 RSASSA-PKCS1-v1_5 using SHA-384 秘密鍵
RS512 RSASSA-PKCS1-v1_5 using SHA-512 秘密鍵
ES256 ECDSA using P-256 and SHA-256 秘密鍵
ES384 ECDSA using P-256 and SHA-384 秘密鍵
ES512 ECDSA using P-256 and SHA-512 秘密鍵
PS256 RSASSA-PSS using SHA-256 and MGF1 with SHA-256 秘密鍵
PS384 RSASSA-PSS using SHA-256 and MGF1 with SHA-384 秘密鍵
PS512 RSASSA-PSS using SHA-256 and MGF1 with SHA-512 秘密鍵
none 暗号化なし なし

保存したいデータの実態部分になります。 ペイロードに指定できる項目は「クレーム」と呼ばれ、あらかじめ決められた「予約済みクレーム」と発行者が任意に指定する「プライベートクレーム」の2種類があります。

「プライベートクレーム」は「予約済みクレーム」と衝突しなければ好きなように作れるので、ここでは「予約済みクレーム」だけ紹介します。

{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022
}
項目 名称 説明
iss Issuer 任意項目。文字列かURI。 発行者の識別子。
sub Subject 任意項目。文字列かURI。 同じIssuer内で一意になる値(リソースオーナーのユーザー識別子)。
aud Audience 任意項目。1件の場合は単一の文字列かURI。 複数件の場合は文字列またはURIの配列。受益者の識別子(クライアントID)。
exp Expiration Time 任意項目。NumericDate(エポック秒)。 JWTを失効させる日時。
nbf Not Before 任意項目。NumericDate(エポック秒)。 JWTが有効になる日時。
iat Issued At 任意項目。NumericDate(エポック秒)。 JWTの発行日時。
jti JWT ID 任意項目。文字列。 JWTを一意に識別するための値。 再発行を防ぐためのものなので、JWTが発行されるたびに変わる。

発行された JWT が改ざんされていないかを確認するための証明になります。 「ヘッダーをエンコードしたもの」と「ペイロードをエンコードしたもの」をもとに署名を作成します。

HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  YOUR-SECRET
)

使い方

通常はリクエスト/レスポンスのヘッダーに埋め込みます。 具体的には Authorization ヘッダーの Bearer スキーマ に指定して送受信します。

Authorization: Bearer <token>

注意点

JWTを使うときはセキュリティ面に注意が必要です。 ここでは特に気を付けておきたい注意点をまとめます。

  • 重要な情報は保存しない

    Base64URLエンコードされただけなので、盗聴されると誰でも中身が確認できてしまいます。 常時HTTPSが言われる昨今でなかなか難しい話ですが、念のため避けるのがよいでしょう。

  • algは公開鍵暗号のものしか受け付けない

    alg: none に改ざんされると誤って改ざんされたJWTを受け入れる懸念があります。 仮に何かしらの公開鍵暗号を使っていたとしても alg: HSxxx (共通鍵) に変更されると、「公開鍵文字列を共通鍵として利用して」署名を生成され、誤って受け入れる懸念があります。

今回は「JSON Web Token (JWT)」についてまとめました。 参考になったでしょうか? 本記事がお役に立っていると嬉しいです!!

参考記事

最後に… このブログに興味を持っていただけた方は、 ぜひ 「Facebookページ に いいね!」または 「Twitter の フォロー」 お願いします!!