JWT(Json Web Token)とは?トークンのデータ構造と暗号化の仕組み。

JWT(Json Web Token)とは?トークンのデータ構造と暗号化の仕組み。

この記事では、ウェブアプリケーションの制作でよく使用されるJson Web Token(以下JWT)について説明する。

JWTは特にウェブの世界を中心に広く普及しているトークンの仕様であり、ウェブ系の開発者であれば知っておきたい技術である反面、セキュリティ面での問題から使用するべきでは無いという主張もある。

今回はJWTの特徴やその長所を活かした運用方法なども併せて説明したい。

JWT(Json Web Token)とは?

JWT公式ページ:: jwt.io

JWT(Json Web Token)とは、HTTPリクエストの際に用いられるトークンであり、ユーザーやデバイスの識別と権限の有無を確認するために使用される。

「ジョット」といった感じに発音される。

特にウェブの世界において広く普及している技術であり、Python・Java・JavaScriptなど様々なプログラミング言語でのライブラリが用意されている。

JWTの仕様はRFC 7519にて定義されている。

JWTは権限付与のスタンダードであるOAuth 2.0において標準で使用される。
OAuth 2.0について知りたい人はこちらの記事を読んでほしい。

JWTの特徴

Json Web Tokenはその名の通り、JSONデータの構造を使用して認証情報を記録している。

また、JWTではパスワードなどのクレデンシャルをトークン自身に記録している点も大きな特徴である。

情報はすべて暗号化されて記録されているために覗き見することは出来ない。また、暗号化にはシークレットキーを使用しているため、クライアント側でトークンの内容を改竄することが出来ない。

JWTの長所

JWTが普及するまでは、セッションIDをCoockieとして使用することによりリクエストの認可とユーザーの識別をおこなっていた。

JWTは従来のセッションを使用した方式と比較して以下のような長所がある。

  • セッション情報をサーバー側のDBなどにセーブする必要が無い。
  • 複数のバックエンドサーバーを利用している場合でもひとつのJWTでリクエストができる。

JWTの短所と脆弱性

JWTは認証情報をトークン自体に記録するため、サーバーにてトークンの状態管理をおこなわない限りトークンを無効にすることが出来ない。

ただし、サーバーにトークンの状態を記録するならばデーターベースへのアクセスが必要となり、JWTの長所が失われる。

いずれにせよ実際のプロダクトにJWTを導入するならば、サーバー側でトークンの有効性をコントールする仕組みが必要となるだろう。

なお、JWTではヘッダーの記述に関する脆弱性が報告されており、algの値が”none”である場合は処理を受け付けないなどの対処をするべきとされている。

JWTの構造

次にJWTに納められている情報について詳しく見ていこう。

JWTは以下の3つのパートから構成されている。

  • ヘッダー (header)
  • ペイロード (payload)
  • 署名 (signature)

ヘッダー

ヘッダーには”typ”、”alg”という2つのプロパティが納められている。

“typ”には「JWT」が指定され、”alg”には署名を検証する際に使用するアルゴリズムが格納されている。署名には「HS256」「RS256」がよく使用される。

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

ペイロード

ペイロードには認証に関する任意の情報を納めることができる。

以下の7つのプロパティは標準で用意されている。

プロパティ名称内容
issIssuer発行者の情報
subSubjectテーマの情報
audAudienceトークンの受信者のための識別子
expExpiration Timeトークンの有効期限
nbfNot Beforeトークンの開始日時
iatIssued atトークンの発行日時
jtiJWT IDトークン自身の識別子
{
  "role": "user",
  "jti": 123456789
}

署名

署名はトークンの有効性を検証するために使用される。

Base64URL方式で符号化されたヘッダーとペイロードをピリオドを挟み連結して、うえでキーシークレットと共に指定したアルゴリズムで暗号化される。

HMACSHA256(

  base64urlEncoding(header) + '.' +
  base64urlEncoding(payload),
  secret-key
)

JWTの公式ページでは、トークンに含まれる情報とエンコードされたトークンの値を比較することができる。