3秒でわかる
jsonwebtoken パッケージでトークンを発行する関数。中身と秘密鍵と有効期限を渡し、署名付きの文字列を作ります。
もう少し詳しく
どういうものか
Node.js の jsonwebtoken パッケージが提供する、JWT を組み立てて署名する関数。第 1 引数に中身となるオブジェクト、第 2 引数に秘密鍵、第 3 引数に有効期限などのオプションを渡すと、ドットで区切られた 3 つの部分からなる文字列が返る。3 つはヘッダー、ペイロード、署名にあたる。
署名は、ヘッダーとペイロードを秘密鍵でハッシュしたもの。鍵を知らない者は署名を作れないため、中身を書き換えたトークンは検証時に必ず弾かれる。
なぜ必要か
ログイン状態をサーバー側のセッションで持つと、リクエストのたびに保存先を引きにいくことになる。JWT なら、必要な情報がトークンそのものに入っていて、正しさは署名だけで確かめられる。サーバーを複数台に並べても、セッションの共有を考えずに済む。
具体例
const jwt = require("jsonwebtoken");
// 発行する
const token = jwt.sign(
{ sub: user.id, role: user.role }, // ペイロード
process.env.JWT_SECRET, // 秘密鍵は環境変数から
{ expiresIn: "1h" } // 1時間で失効
);
// 検証する
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
console.log(payload.sub);
} catch (err) {
// 期限切れ、または署名が合わない
console.error(err.name);
}expiresIn を渡すと、ペイロードに exp が自動で入り、verify のときに期限が判定される。
つまずきやすいところ
最も危険なのが、ペイロードを暗号化だと思い込むこと。JWT の中身は Base64URL でエンコードされているだけで、誰でも復号せずに読める。パスワードや個人情報を入れてはいけない。改ざんは防げるが、秘匿はできない。
秘密鍵をソースコードに直書きするのも典型的な事故になる。リポジトリに載った時点で、誰でも任意のトークンを発行できてしまう。環境変数やシークレット管理サービスから読む。
有効期限を長くしすぎるのも問題になる。JWT はサーバー側に状態を持たないため、発行済みのトークンを個別に無効化できない。アクセストークンは短めにし、更新用のリフレッシュトークンを別に持たせる構成が一般的になる。
似た用語との違い
| 関数 | 役割 |
|---|---|
jwt.sign | 中身から署名付きトークンを作る |
jwt.verify | 署名と期限を確かめ、中身を返す。失敗すると例外 |
jwt.decode | 署名を確かめずに中身だけ読む。認証には使えない |