3秒でわかる
受け取った JWT の署名と有効期限を検査し、中身の payload を安全に取り出す関数。改ざんされたトークンをここで弾きます。
もう少し詳しく
どういうものか
jwt.verify は、Node.js の jsonwebtoken ライブラリが提供する検証用の関数です。トークン文字列と秘密鍵を渡すと、署名が正しいか、有効期限が切れていないかを調べ、問題がなければ payload をオブジェクトとして返します。どこかが合わなければ例外を投げます。
JWT はドットで区切られた3つの部分から成り、ヘッダーと payload は Base64URL で符号化されているだけです。つまり中身は誰でも読めます。読めることと信用できることは別で、その信用を担保するのが3つ目の署名であり、それを照合するのが jwt.verify です。
なぜ必要か
トークンは利用者のブラウザに預ける以上、途中で書き換えられる前提で扱う必要があります。userId を他人の値に差し替えたトークンが送られてきても、秘密鍵を知らなければ正しい署名は作れません。検証を通すことで、そのトークンが自分のサーバーが発行したものだと確認できます。
具体例
Express のミドルウェアとして使う例です。
import jwt from "jsonwebtoken";
export function auth(req, res, next) {
const header = req.headers.authorization ?? "";
const token = header.startsWith("Bearer ") ? header.slice(7) : null;
if (!token) return res.status(401).json({ error: "no token" });
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
req.userId = payload.sub;
next();
} catch (e) {
// 期限切れは TokenExpiredError、署名不一致は JsonWebTokenError
return res.status(401).json({ error: "invalid token" });
}
}つまずきやすいところ
もっとも危険な間違いは、jwt.decode で済ませてしまうことです。decode は署名を一切見ずに payload を取り出すだけなので、偽造トークンをそのまま信用します。検証が要る場所では必ず verify を使います。
algorithms を指定しない設定も穴になります。アルゴリズムを固定しておかないと、攻撃者が none や別方式を指定したトークンを送り込む余地が残ります。jwt.verify(token, secret, { algorithms: ["HS256"] }) のように限定します。
期限切れと署名不正を同じ扱いにして、利用者に「ログインし直してください」としか出せない実装もよくあります。例外の name を見れば区別できるので、再ログインを促すか不正として記録するかを分けられます。
似た用語との違い
jwt.sign は発行、jwt.decode は署名を見ない読み取り、jwt.verify は検証付きの読み取りです。サーバー側で扱うのは sign と verify の2つだけ、と覚えておくと迷いません。