この記事では、JWTの仕組みと注意点を紹介します。
対象読者は、JWTをなんとなく使っているが、仕組みについて自信を持って説明できない人です。
この記事を読めば、JWTを扱うコードを読んだときに何をしているのか理解でき、セキュリティ上の落とし穴を避けられるようになります。
ぜひ最後までご覧ください。
JWTとは何か
JWTとは、認証した事実を証明するトークン形式の1つです。正式名称はJSON Web Tokenで、「ジョット」と読みます。
Cookieを使ったセッション管理の仕組みの記事で紹介した「クライアントサイド方式」の代表例がJWTです。ユーザー情報に署名を付けてトークンとして発行し、ブラウザに保存させます。
JWTの最大のメリットは、認証サービスにアクセスせずにユーザー情報を取得できることです。サーバーサイド方式では、リクエストのたびにデータベースやRedisにセッション情報を問い合わせる必要があります。JWTなら、トークン自体にユーザー情報が含まれているため、この問い合わせが不要になります。

JWTの構造
JWTは、ドット(.)で区切られた3つのパートで構成されています。
xxxxx.yyyyy.zzzzz
それぞれHeader、Payload、Signatureと呼ばれます。
Header
{ "alg": "HS256", "typ": "JWT" }
Payload
ユーザーIDや有効期限など、実際に伝えたい情報(クレーム)を格納します。
{ "iss": "https://example.com", "sub": "1234567890", "aud": "https://api.example.com", "exp": 1735689600, "iat": 1735686000, "jti": "abc123" }
RFC 7519では、以下の登録済みクレームが定義されています。いずれも必須ではありませんが、よく使われるものです。
iss(Issuer): トークンの発行者sub(Subject): トークンの主体(通常はユーザーID)aud(Audience): トークンの受信者(このトークンを受け入れるべきサービス)exp(Expiration Time): 有効期限iat(Issued At): 発行日時jti(JWT ID): トークンの一意な識別子(リプレイ攻撃対策に使用)
これらに加えて、アプリケーション独自のクレーム(例: name、roleなど)を追加することもできます。
Signature
HeaderとPayloadを秘密鍵で署名したものです。これにより、トークンが改ざんされていないことを検証できます。
HeaderとPayloadはBase64エンコードされているだけなので、トークンを受け取ったクライアント側でデコードして中身を見ることができます。署名は改ざん検知のためのものであり、暗号化ではありません。この点は非常に重要です。
JWTの注意点
JWTを安全に使うためには、いくつかの注意点があります。
署名を必ず検証する
Base64デコードすればPayloadの中身が見られるため、署名を検証しなくてもクライアント側でユーザー情報を取得できてしまいます。
しかし、署名を検証しないと、攻撃者が偽造したトークンを受け入れてしまう危険があります。トークンを受け取ったら、必ず以下を検証してください。
- 署名が正しいか
- 有効期限(
exp)が切れていないか - 発行者(
iss)が期待する値か - 受信者(
aud)が自分のサービスを指しているか
署名アルゴリズムを適切に管理する
署名アルゴリズムに関連した攻撃手法がいくつか知られています。対策として、以下を心がけてください。
Payloadに機密情報を入れない
前述の通り、Payloadはクライアント側でデコードして中身を見ることができます。パスワードやクレジットカード番号などの機密情報は絶対に入れないでください。
ログアウト処理の難しさ
JWTの大きな課題は、一度発行したトークンをサーバー側から即座に無効化できないことです。
サーバーサイド方式なら、データベースからセッション情報を削除すれば即座にログアウトできます。しかしJWTは、トークン自体が有効期限を持っているため、期限が切れるまで有効なままです。
この問題への対策は主に2つあります。
トークンの有効期限を短くする
有効期限を数分〜数十分と短く設定します。期限が切れたら、ユーザーに再度ログインしてもらうか、別途発行した長寿命のリフレッシュトークンを使って新しいJWTを取得させます。万が一トークンが漏洩しても、有効期限が短ければ被害を最小限に抑えられます。
無効化リストを管理する
ログアウトしたJWTのID(jtiクレーム)をデータベースに保存しておき、トークン検証時にチェックします。ただし、この方法はサーバーサイドでの問い合わせが必要になるため、JWTの「問い合わせ不要」というメリットが薄れます。
さいごに
JWTの仕組みと注意点について、理解していただけましたでしょうか?
JWTは便利ですが、仕組みを理解せずに使うとセキュリティリスクにつながります。まずは自分のプロジェクトで、JWTがどのように発行・検証されているか確認してみてください。
最後までご覧いただきありがとうございました。また別の記事でお会いしましょう。