はじめに

Webアプリケーションを開発していると、「JWT」という言葉をよく目にします。ログイン機能やAPI認証で使われる重要な技術ですが、最初は少しとっつきにくいかもしれません。

この記事では、JWTの基本を初心者向けにわかりやすく解説します。

JWTとは?

JWT(JSON Web Token) は、情報を安全にやり取りするためのトークン形式です。

簡単に言うと、「誰が何の権限を持っているか」を証明するデジタルな身分証明書のようなものです。

なぜJWTが必要なの?

従来のWebアプリケーションでは、ログイン状態をサーバー側の「セッション」で管理していました。しかし、この方法にはいくつかの課題があります。

方式特徴
セッション方式サーバーがログイン状態を記憶する必要がある
JWT方式トークン自体に情報が含まれ、サーバーは記憶不要

JWTを使うと、サーバーは状態を持たなくて済むため(ステートレス)、複数のサーバーに分散させやすくなります。

JWTの構造

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

1
2
3
xxxxx.yyyyy.zzzzz
              
Header.Payload.Signature

実際のJWTはこのような文字列です。

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30

一見すると暗号のように見えますが、実はBase64URLでエンコードされているだけです。

1. Header(ヘッダー)

トークンのタイプと、署名に使うアルゴリズムを指定します。

1
2
3
4
{
  "alg": "HS256",
  "typ": "JWT"
}
  • alg: 署名アルゴリズム(HS256, RS256など)
  • typ: トークンのタイプ(JWT)

2. Payload(ペイロード)

実際に伝えたい情報(クレームと呼ばれます)が含まれます。

1
2
3
4
5
6
{
  "sub": "1234567890",
  "name": "John Doe",
  "iat": 1516239022,
  "exp": 1516242622
}

よく使われるクレーム(予約済み):

クレーム説明
subSubject(主題)- ユーザーIDなど
iatIssued At(発行日時)
expExpiration(有効期限)
issIssuer(発行者)
audAudience(対象者)

注意: Payloadは暗号化されていません。Base64でデコードすれば誰でも中身を見れます。パスワードなどの機密情報は絶対に入れないでください。

3. Signature(署名)

ヘッダーとペイロードを結合し、秘密鍵で署名したものです。

1
2
3
4
HMACSHA256(
  base64UrlEncode(header) + "." + base64UrlEncode(payload),
  secret
)

この署名により、トークンが改ざんされていないことを検証できます。

JWTの流れ

実際の認証フローを見てみましょう。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
1. ユーザー: IDとパスワードでログイン
2. サーバー: 認証OK → JWTを発行して返す
3. クライアント: JWTを保存(localStorageやCookieなど)
4. クライアント: APIリクエスト時にJWTを送信
   Authorization: Bearer eyJhbGciOi...
5. サーバー: JWTの署名を検証 → OKならリクエストを処理

JWTを実際に見てみよう

jwt.io というサイトで、JWTをデコードして中身を確認できます。

試しに以下のトークンをデコードしてみてください。

1
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

JWTのメリット・デメリット

メリット

  • ステートレス: サーバーがセッション情報を保持する必要がない
  • スケーラブル: 複数サーバー間で共有しやすい
  • クロスドメイン: 異なるドメイン間でも使いやすい
  • モバイルフレンドリー: ネイティブアプリでも扱いやすい

デメリット

  • トークンサイズ: セッションIDより大きくなりがち
  • 無効化が難しい: 発行したトークンを途中で無効にするのが難しい
  • Payload丸見え: 暗号化されていないので機密情報は入れられない

セキュリティの注意点

JWTを安全に使うために、以下の点に注意しましょう。

1. 秘密鍵は厳重に管理する

秘密鍵が漏れると、誰でもトークンを偽造できてしまいます。

2. 有効期限を短くする

expクレームで有効期限を設定し、できるだけ短くしましょう。長期間有効なトークンはリスクが高くなります。

3. HTTPSを使う

JWTは平文で送信されるため、必ずHTTPSで通信しましょう。

4. 機密情報をPayloadに入れない

Payloadは暗号化されていません。パスワードやクレジットカード番号などは絶対に入れないでください。

5. アルゴリズムを固定する

サーバー側で受け入れるアルゴリズムを明示的に指定しましょう。alg: none攻撃を防ぐためです。

よくある質問

Q: JWTはどこに保存すべき?

A: 用途によりますが、一般的には以下の選択肢があります。

保存場所特徴
HttpOnly CookieXSS攻撃に強い。CSRF対策が必要
localStorage使いやすいがXSS攻撃に弱い
メモリ(変数)最も安全だがページリロードで消える

セキュリティを重視するならHttpOnly Cookieがおすすめです。

Q: JWTとセッションどちらを使うべき?

A: どちらが良いかは要件次第です。

  • JWT向き: マイクロサービス、SPA、モバイルアプリ、サーバーレス
  • セッション向き: 従来のWebアプリ、即座にログアウトさせたい場合

まとめ

JWTの基本をまとめると以下の通りです。

  • JWTはHeader.Payload.Signatureの3部構成
  • Payloadに情報を含み、Signatureで改ざんを検知
  • ステートレスな認証を実現できる
  • Payloadは暗号化されていないので機密情報は入れない
  • 有効期限HTTPSでセキュリティを確保

JWTは現代のWeb開発において欠かせない技術です。基本を理解した上で、適切に活用していきましょう。

参考リンク

  • JWT.IO - JWTのデコード・検証ツール
  • RFC 7519 - JWT の公式仕様

理解度チェック

理解度チェッククイズ(全5問)
問1

JWTが「ステートレス」と呼ばれるのはなぜですか?

答えサーバーがログイン状態を保持せず、トークン自体に必要な情報が含まれているため。

問2

JWTのPayloadにパスワードなどの機密情報を入れてはいけない理由は何ですか?

答えPayloadは暗号化されておらず、Base64デコードすれば誰でも中身を見られるため。

問3

JWTのSignature(署名)は何を保証するためのものですか?

答えトークンが発行後に改ざんされていないことを保証するため。

問4

JWTを使った認証で、クライアントはAPIリクエスト時にトークンをどこに送りますか?

答えHTTPヘッダーの `Authorization: Bearer ` に含めて送信する。

問5

JWTに exp(有効期限)を設定するのはなぜですか?

答えトークンが漏洩した場合の被害を最小限に抑えるため。

問6

JWTは途中で無効化しづらいという欠点があります。 この問題を軽減するために、よく使われる設計は何でしょう?

答え有効期限を短くし、リフレッシュトークンと組み合わせて運用する。