【入門編】JWTのクレーム検証におけるiss, aud, expの厳密なチェック実装 – アプリケーションセキュリティ & 安全な開発防御ガイド

鍵を渡した相手は誰?JWTの「3つの確認ポイント」で防ぐセッションハイジャック

こんにちは。セキュリティの現場で日々、複雑な攻撃と対峙しているエンジニアです。

今日は、現代のWebアプリケーションで「通行手形」として広く使われているJWT(JSON Web Token)についてお話しします。

「JWTって難しそう…」と思うかもしれませんが、イメージしてみてください。JWTは「名札付きの鍵」です。この鍵さえ持っていれば、ホテルやマンションの部屋(サーバーのリソース)に入ることができます。でも、もしその鍵が偽物だったり、期限切れだったりしたらどうでしょう?

今回は、新人の開発者さんがつい見落としがちな、「JWTを厳密にチェックするための3つの鉄則」を、身近な防犯に例えて解説します。

—

1. なぜ「確認」をサボると危険なのか?

泥棒は、鍵を作るのが得意です。もし皆さんが「鍵が提示されたこと」だけを確認して、「その鍵が本当にこのホテルのものか?」「期限は切れていないか?」をチェックしなかったらどうなるでしょうか?

攻撃者は、どこか別の場所で盗んだ鍵(他サイトのJWT)をあなたのサイトに持ち込み、「自分はこのホテルの宿泊客だ!」と嘘をついて侵入してきます。これがセッションハイジャックの入り口です。

これを防ぐために、JWTには以下の3つの「身分証明」が含まれています。

  • iss (Issuer): 「誰がこの鍵を発行したのか?」
  • aud (Audience): 「この鍵は誰のために発行されたのか?」
  • exp (Expiration Time): 「いつまで有効なのか?」

この3つを厳密にチェックしないということは、「誰が書いたかもわからない、いつの時代のかもわからない名札」を信じて、部屋のドアを全開にしているのと同じなのです。

—

2. 厳密な検証を実装する(コード例)

では、具体的にどのようにコードを書けばよいのでしょうか?ライブラリ任せにせず、しっかりオプションを設定することが重要です。

ここでは、Node.jsでよく使われる jsonwebtoken ライブラリを例に、安全な検証設定を見てみましょう。

const jwt = require(‘jsonwebtoken’);

const token = “受け取ったJWT”;
const secretKey = “サーバー側で管理している秘密鍵”;

// 検証オプションを厳密に設定します
const verifyOptions = {
issuer: ‘https://auth.myapp.com’, // 信頼できる発行元を指定
audience: ‘https://api.myapp.com’, // このAPIのために発行されたものか確認
algorithms: [‘HS256’] // 許可するアルゴリズムを限定(重要!)
};

try {
// 検証実行:ここで exp (有効期限) も自動的にチェックされます
const decoded = jwt.verify(token, secretKey, verifyOptions);

console.log(“認証成功!”, decoded);
} catch (err) {
// 検証に失敗したら即座にアクセス拒否
console.error(“不正な鍵です!”, err.message);
}

なぜこの設定が大切なのか?

  • issuer (iss) のチェック: 「偽の発行元」からの鍵を弾きます。近所の公園で拾った名札を、ホテルの鍵として使わせないためです。
  • audience (aud) のチェック: 「自分宛てではない鍵」を弾きます。例えば、皆さんのサイトの鍵を別の悪意あるサイトで使い回そうとする攻撃を防ぎます。
  • algorithms の指定: これを忘れると、攻撃者が署名を「なし(noneアルゴリズム)」に改ざんした偽造トークンを通してしまうリスクがあります。「署名は必ず特定のアルゴリズムで検証する」と指定するのがプロの流儀です。

—

3. 「有効期限(exp)」は泥棒を追い出す防犯ブザー

特に exp(有効期限)のチェックは、泥棒対策において最も強力な武器です。

もし、あるユーザーがスマホを紛失したとします。もしJWTに期限がなかったら、そのスマホを拾った人は永遠にあなたのサイトにログインできてしまいます。しかし、「この鍵は1時間だけ有効」と決めておけば、時間が経てば鍵は自動的に無効になります。

現場の教訓:
開発中にテストのために期限を「100年後」などに設定するケースがありますが、そのまま本番環境にデプロイするのは厳禁です。有効期限は「必要最小限」にするのが、セキュリティの鉄則ですよ!

—

最後に:一歩ずつ、強固なシステムへ

セキュリティ対策とは、一度やって終わりではありません。

「鍵を確認したか?」
「発行元は正しいか?」
「期限は切れていないか?」

こうした一つひとつの積み重ねが、あなたのアプリケーションを、そしてユーザーの大切なデータを守る強固な盾になります。最初は難しく感じるかもしれませんが、こうして一つずつ学んでいけば大丈夫です。

まずは今すぐ、あなたのソースコードにある「JWT検証部分」を覗いてみてください。「なんとなく動いている」から、「意図して守っている」コードへ。一緒にアップデートしていきましょう!

何か不明な点があれば、いつでもエンジニア仲間として相談してくださいね。それでは、また!

コメント

タイトルとURLをコピーしました