【今更ながら】 JWT の仕組みについて解説

  • JWT
  • 認証

本記事では、 JWT の仕組みを詳細に解説し、実際の使用例を交えながら説明します。

JWT (JSON Web Token) は、Web開発の世界で広く使用されている認証および情報交換のための開放型標準(RFC 7519)です。

読み方は 「ジョット」 だと思っています。

JWT とは

JWT は、端的に言ってしまうと、当事者間で安全に情報を送信するための、コンパクトで自己完結型の方法です。

この「安全に情報を送信」という理由としては、デジタル署名されているため、検証および信頼することが挙げられます。

JWT は、 HMAC アルゴリズムまたは RSA・ECDSA などの公開鍵/秘密鍵ペアを使用して署名することができます。

(HMAC アルゴリズムやRSA・ECDSA についての説明は割愛)

JWT の構造

JWT は、ドット(.)で区切られた3つの部分から構成されています。

  1. ヘッダー(Header)
  2. ペイロード(Payload)
  3. 署名(Signature)

典型的な JWT は次のような形式で表現されます。

xxxxx.yyyyy.zzzzz

それぞれの部分を少し詳しく見ます。

1. ヘッダー 部について

JWT のヘッダーは通常、トークンのタイプ(JWT)と使用している署名アルゴリズム(例:HMAC SHA256やRSA)の2つの部分から構成されています。

Sponsored

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

この JSON は、 Base64Url でエンコードされてトークンの最初の部分を表しています。

2. ペイロード 部について

トークンの2番目の部分は、クレーム(claims)を含むペイロードです。

クレームとは、エンティティ(通常はユーザー)とその他の追加のメタデータに関するステートメントです。

ここに、ユーザ名 等 が含まれることが多いです。

{
  "sub": "1234567890",
  "name": "Sample Taro",
  "admin": true,
  "iat": 1516239022
}

このペイロードも Base64Url でエンコードされて、トークンの2番目の部分となります。

3. 署名 部について

署名を作成するには、エンコードされたヘッダー、エンコードされたペイロード、シークレット、ヘッダーで指定されたアルゴリズムを使用します。

例えば、HMAC SHA256 アルゴリズムを使用する場合、署名は以下のように作成されます。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

この署名は、メッセージが途中で変更されていないことを確認するために使用されます。

Sponsored

JWT の基本的な動作プロセス

  1. ユーザーがログインすると、サーバーは先ほど説明したような方法でJWTを生成します。
  2. サーバーはこのトークンをクライアントに返します。
  3. クライアントは以降のリクエストで、このトークンを(通常は Authorization ヘッダーに)含めて送信します。
  4. サーバーは受け取ったトークンを検証し、有効であれば要求された操作を許可します。
JWT認証プロセス JWT認証プロセス ログインでトークンを受け取り、その後のAPI呼び出しで検証して使う クライアント 認証サーバー APIリソース 1. ログインリクエスト(認証情報)
<rect x="390" y="208" width="20" height="44" rx="10" fill="#2a9d8f" stroke="none" />
<text x="446" y="235" font-size="13" fill="#171717">2. JWTを生成</text>

<path d="M400 264H108" />
<text x="254" y="250" text-anchor="middle" font-size="13" fill="#171717">3. JWTを返却</text>

<rect x="282" y="284" width="236" height="28" rx="14" fill="#fffaf2" stroke="#d7c8b4" stroke-width="2" />
<text x="400" y="303" text-anchor="middle" font-size="12" fill="#5a5247">Authorization: Bearer &lt;JWT&gt;</text>

<path d="M108 332H692" />
<text x="400" y="318" text-anchor="middle" font-size="13" fill="#171717">4. 保護されたリソースをリクエスト</text>

<path d="M692 400H400" />
<text x="546" y="386" text-anchor="middle" font-size="13" fill="#171717">5. トークン検証を依頼</text>

<rect x="390" y="414" width="20" height="52" rx="10" fill="#2a9d8f" stroke="none" />
<text x="446" y="432" font-size="13" fill="#171717">6. 署名と有効期限を確認</text>

<path d="M400 482H692" />
<text x="546" y="468" text-anchor="middle" font-size="13" fill="#171717">7. 検証結果を返す</text>

<path d="M692 536H108" />
<text x="400" y="522" text-anchor="middle" font-size="13" fill="#171717">8. リソースを返却</text>

jwt.ioでのサンプル

jwt.io というサービスを使用して、実際のJWTをエンコード/デコードしてみましょう。

以下のJWTを例として使用します。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

jwt.io にアクセスし、このトークンを Encoded セクションに貼り付けると、自動的にデコードされます。

Decoded セクションで、ヘッダー、ペイロード、署名を確認できます。

jwt-sample

JWTの利点

  • ステートレスである点 サーバーはユーザーセッションを保存する必要がありません。
  • 使いやすいJSON形式 JWTはJSON形式なので、多くのプログラミング言語で扱いやすいです。
  • 強固なセキュリティ デジタル署名により、改ざんを防ぐことができます。

JWT を扱う際の注意点

  • サイズ JWTにはペイロードサイズの制限がないため、大きすぎるトークンは避けるべきです。
  • 秘密鍵の管理 署名に使用する秘密鍵は、安全に管理する必要があります。
  • 有効期限 適切な有効期限を設定し、必要に応じてトークンを更新する仕組みを実装すべきです。

おわりに

JWT は、モダンなWeb開発において重要な役割を果たす認証メカニズムです。

仕組みを理解して適切に使用すれば、セキュアで効率的なアプリケーション開発ができますね。