API の認証を調べていると、リクエストヘッダーや Cookie に eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTEyMyJ9.xxxx のような長い文字列が登場することがあります。これが JWT(JSON Web Token) です。

この記事では、JWT の仕組みと構造、デコード方法、よくある使いどころとセキュリティの注意点を整理します。

JWT とは

JWT(読み方: ジョット)は、情報を JSON 形式で安全にやりとりするためのコンパクトなトークン形式です。RFC 7519 として標準化されており、主に Web API の認証・認可に使われています。

JWT の最大の特徴は、サーバーがトークンを検証できる点です。署名(Signature)を確認することで、トークンが改ざんされていないかどうかをサーバーサイドで判断できます。

JWT の構造

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

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJzdWIiOiJ1c2VyLTEyMyIsImlhdCI6MTY5OTk5OTAwMCwiZXhwIjoxNzAwMDg1NDAwfQ
.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

各パートはそれぞれ Base64URL エンコードされています(詳しくは後述)。

パート内容説明
Header{"alg":"HS256","typ":"JWT"}アルゴリズムとトークン種別
Payload{"sub":"user-123","exp":...}ユーザーIDや有効期限などのクレーム
Signatureハッシュ値ヘッダー+ペイロードの署名。改ざん検証に使う

Base64URL エンコードとは

JWT の各パートは Base64URL でエンコードされています。Base64 との違いは、URL に含められない文字(+-/_)が置き換えられている点です。パディング文字(=)も省略されます。

Base64URL は暗号化ではなく、単なるエンコードです。デコードすれば誰でも中身を読めます。JWT の安全性はあくまで Signature の検証によって担保されており、ペイロードの内容は原則として秘匿されていません。

ペイロードの主要クレーム

ペイロードには「クレーム(Claims)」と呼ばれるキーバリューが格納されます。RFC で定義された予約済みクレームの代表例を示します。

クレーム意味
exp有効期限(Expiration Time)UNIX タイムスタンプ(秒)
iat発行日時(Issued At)UNIX タイムスタンプ(秒)
nbf有効開始日時(Not Before)UNIX タイムスタンプ(秒)
subトークンの主体(Subject)文字列(ユーザーID など)
iss発行者(Issuer)文字列(URL など)
aud受信者(Audience)文字列または配列
jti一意識別子(JWT ID)文字列

exp(有効期限)は特によく使われます。現在の UNIX タイムスタンプと exp を比較することで、トークンが期限切れかどうかを判断できます。

// 期限切れチェック(JavaScript)
const now = Math.floor(Date.now() / 1000);
const isExpired = now > jwtPayload.exp;
console.log(isExpired ? '期限切れ' : '有効');

よくある使いどころ

API の認証(Bearer トークン)

最も一般的な使い方は、HTTP リクエストの Authorization ヘッダーに付与する Bearer トークンとしての使用です。

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.xxxxx

サーバーは受け取ったトークンの署名を検証し、exp が未来であれば認証済みとして処理します。

Cookie への格納

SPA(シングルページアプリ)では HttpOnly Cookie に JWT を格納するパターンも一般的です。JavaScript から直接アクセスできないため、XSS による窃取リスクが下がります。

SSO・マイクロサービス間の認証

サービス間で共通の秘密鍵または公開鍵ペアを共有することで、JWT を使ったシングルサインオンや、マイクロサービス間の認証が実現できます。

JWT をデコードする方法

ペイロードの内容を確認したい場合は、. で分割して2番目のパートを Base64URL デコードするだけです。

// JavaScript でデコード
function decodeJWT(token) {
  const payload = token.split('.')[1];
  // Base64URL → Base64 に変換してデコード
  const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');
  return JSON.parse(atob(base64));
}

const decoded = decodeJWT('eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyLTEifQ.xxx');
console.log(decoded); // { sub: 'user-1' }

手動でデコードする場合はツールを使う方が簡単です。

JWT デコーダー 貼り付けるだけで header / payload を即デコード。exp の有効期限も自動判定。
ツールを使う →

セキュリティの注意点

まとめ

関連記事