3秒でわかる
ログイン済みであることを、署名付きの文字列そのものに書いて持ち歩かせる方式。サーバーが状態を預からずに済むので、複数台に分散した API でも認証が通ります。
30秒図解
もう少し詳しく
どういうものか
JWT (JSON Web Token) は、利用者の情報を JSON で書き、それに改ざん検知用の署名を付けて 1 本の文字列にしたものです。ドットで区切られた 3 つの部分から成り、前からヘッダー、ペイロード、署名という並びになっています。
ヘッダーとペイロードは Base64URL で符号化されているだけなので、誰でも中身を読めます。読めなくする仕組みではなく、書き換えられたら分かる仕組みだ、というのが最初に押さえる点です。署名は秘密鍵を持つサーバーしか作れないため、1 文字でも改ざんすると検証に失敗します。
なぜ必要か
従来のセッション方式は、ログイン状態をサーバー側のメモリやデータベースに保存します。サーバーが 1 台なら問題ありませんが、負荷分散で 3 台に増やすと、別の台に届いたリクエストが「知らない利用者」になってしまいます。JWT はログイン状態をトークン側に書いて持たせるので、どの台でも署名を検証するだけで判断でき、保存場所を共有せずに済みます。
具体例
import jwt from "jsonwebtoken";
const token = jwt.sign(
{ sub: "user_42", role: "admin" },
process.env.JWT_SECRET,
{ expiresIn: "1h" }
);
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
console.log(payload.sub, payload.role);
} catch (e) {
console.log("署名が不正か、有効期限が切れている");
}つまずきやすいところ
パスワードやクレジットカード番号をペイロードに入れてしまう事故が後を絶ちません。前述のとおり中身は誰でも復号でき、ブラウザの開発者ツールに貼れば読めます。入れてよいのは、漏れても致命傷にならない識別子と権限程度です。
有効期限を長くしすぎるのも危険です。一度発行したトークンは、期限が来るまでサーバー側から取り消せません。退会させたはずの利用者が数日間使い続けられる、という状態になります。実用上は寿命を短くし、更新用のリフレッシュトークンと組み合わせます。
似た用語との違い
セッション ID は、サーバー側の記録を引くための単なる番号です。中身を持たないので、無効化はサーバー側の記録を消すだけで済みます。JWT は中身を持つ代わりに、取り消しが苦手です。どちらが上ということはなく、台数と取り消しやすさのどちらを取るかの選択になります。
覚え方
「サーバーが預かる引換券がセッション、本人が持ち歩く署名入り身分証が JWT」と対で覚えます。