- ネットワーク
- 技術 💻
認証とセッションの落とし穴8選|JWT・CSRF・パスキー
ログイン機能って、フレームワーク任せで動いてしまうんですよね。
でも認証は、仕組みを誤解したまま動いてしまうのが一番怖い領域です。動くことと守れていることが、別物なので。今回は、「ログアウトしたのに生きている」トークンの話から、知っていると設計レビューが変わるものを8つ集めました。1つでも知らなかったら儲けものです。
① JWTは、発行したら取り消せません
JWTでの認証は、サーバーがセッションを覚えない「ステートレス」が売りです。
その代償が、これです。一度発行したトークンは、有効期限が切れるまで有効です。ログアウトしても、サーバーは何も覚えていないので、そのトークンを持って来られたら通してしまいます。
「ログアウト=サーバー側で無効化」という常識が、素のJWTでは成立しないんですよね。
だから実務は、有効期限を短くして更新用トークンと組み合わせる、あるいは失効リストを持つ——つまり結局、少しステートを持つ形に落ち着きます。ステートレスは、無効化と引き換えなんです。
② ログイン成功時に、セッションIDを作り直していますか
地味ですが、教科書級に大事なやつです。
攻撃者が先にセッションIDを用意して被害者に踏ませ、被害者がそのIDのままログインすると、攻撃者は「ログイン済みのID」を最初から知っていることになります。セッション固定攻撃です。
対策はたった1つ。ログイン成功の瞬間に、セッションIDを新しく発行し直す。
フレームワークがやってくれることも多いですが、「やってくれているはず」を確認した人は少ない。レビューで一度は見たい1行なんです。
③ Cookieの属性3つは、それぞれ守る敵が違います
Cookieに付ける3つの属性、役割を言い分けられますか。
| 属性 | やること | 守る敵 |
|---|---|---|
HttpOnly | JavaScriptから読めなくする | スクリプト注入(XSS)によるCookie窃取 |
Secure | HTTPSでしか送らない | 通信の盗聴 |
SameSite | 他サイト発のリクエストに付けない | CSRF |
3つセットでよく語られますが、別々の攻撃への、別々の盾です。「なんとなく全部付ける」から「どの敵に効いているか言える」へ。この差が設計の解像度なんです。
④ SameSiteが、CSRF対策の景色を変えました
かつてCSRF対策といえば、フォームごとにトークンを埋め込む方式が定番でした。
いまはChromeやEdgeなどで、SameSiteを指定していないCookieが既定でSameSite=Lax扱いになり、他サイトから飛んでくるPOSTにはそもそもCookieが付きません。攻撃の前提が、ブラウザ側で崩されたんです。
ただし「もうトークン不要」ではありません。この既定の挙動を採用していないブラウザ、None指定のCookie、同一サイト内の抜け道は残ります。
「ブラウザが守ってくれる範囲」と「アプリが守る範囲」の線引きを知っている——それが今のCSRF対策なんです。
⑤ OAuthは「認可」であって、「認証」ではありません
「〇〇でログイン」の裏側でよく起きる誤解です。
OAuthが本来解決しているのは、「このアプリに、私のデータへのアクセスを許可する」という認可です。「この人は誰か」を保証する認証の仕組みではありません。
アクセストークンだけで「本人確認できた」と扱うと、別アプリ向けに発行されたトークンを持ち込まれて成りすまされる穴が生まれます。
だから「ログイン」に使うための拡張として、OpenID Connectが別に存在するんです。似て非なる2つ、役割の違いを知っているだけで事故が1つ減ります。
⑥ パスワード+秘密の質問は、二要素認証ではありません
多要素認証の「要素」には、定義があります。
- 知識(知っているもの)
- 所持(持っているもの)
- 生体(本人であるもの)
この異なる種類を2つ以上組み合わせて、初めて「二要素」です。
パスワードと秘密の質問は、どちらも「知識」。つまり一要素×2回であって、二要素ではありません。片方が漏れる状況では、もう片方も漏れがちだからです。
パスワード+認証アプリなら、知識+所持で二要素。数ではなく、種類なんです。
⑦ MFAでも、フィッシングには敗けることがあります
「多要素にしたから安心」——最後の常識を崩します。
攻撃者が本物そっくりの偽サイトを立て、入力されたパスワードもワンタイムコードも、その場で本物のサイトに転送する——リアルタイム中継型のフィッシングです。コードが正しいので、ログインは成功してしまいます。
これに構造的に強いのが、パスキー(FIDO)です。認証情報がサイトのドメインに暗号的に紐づいているので、偽ドメインでは認証自体が発動しません。
国内でも2025年に証券口座の乗っ取りが相次ぎ、金融業界でフィッシングに耐性のある認証(パスキーなど)の導入が一気に進みました。「フィッシング耐性」という軸で見ると、認証方式の序列が変わって見えるんです。
⑧ トークンを、ログとURLに書いていませんか
最後は、漏れ方の話です。
いまの時代、パスワードそのものよりトークンやセッションIDの漏洩が主戦場です。そして漏れる場所は、攻撃よりも自爆が多い。
- アクセスログに書かれたURL中のトークン
- デバッグログに出力したヘッダ
- エラー通知に添付されたリクエスト全文
- リファラ経由で外部サイトに渡るURLパラメータ
対策は、トークンをURLに載せない、ログのマスキングを共通処理にする、の2つが柱です。認証の強度は、いちばん雑に扱われた場所まで下がるんです。
番外編:知っておくと得する小ネタ
タイムアウトには2種類あります
操作が無い時間で切る「アイドルタイムアウト」と、ログインからの総時間で必ず切る「絶対タイムアウト」。銀行系で「操作していたのに切られた」のは後者で、乗っ取りの被害時間に上限を付ける設計なんです。
「パスワードレス」の正体
魔法ではなく、⑦のパスキーやメールリンクで「知識要素をやめて、所持・生体に寄せる」という要素の置き換えです。⑥の定義が分かると、一気に見通せます。
401と403の違い
401は「誰だか分からない(未認証)」、403は「誰だか分かったうえで駄目」。認証と認可の区別が、ステータスコードにもそのまま現れているんですね。
RJCでも、認証と向き合っています
RJCが携わる保険、金融、決済のシステムは、ログインの向こう側にお金と個人情報がある世界です。②や⑧のような地味な1行が、そのまま信頼になるんですよね。
こういう仕組みの話を、Techチームで共有しながら開発しています。
よくいただくご質問
Q. まずどれから押さえるべきですか?
A. ⑧かなと思います。攻撃を待たずに、今日のログ設定の見直しから始められるんですよね。
Q. セッション方式とJWT、どちらを選ぶべきですか?
A. 無効化を重視するならサーバーセッション、複数サービス間で身元を運ぶならJWTが向きます。①の「取り消せない」を許容できるかが分岐点です。
Q. CSRFトークンは、もう不要ですか?
A. ④のとおり、SameSiteで前提は変わりましたが「不要」ではありません。フレームワークの対策は切らずに、二重の守りにしておくのが定石です。
Q. 未経験からでも、分かるようになりますか?
A. なります。認証は「合鍵・会員証・顔パス」の日常の比喩でほぼ全部説明できる分野なんです。
「誰であるか」と「何をしていいか」を、分けて考える
今日の8つに共通していたのは、これでした。
認証(誰か)と認可(何をしていいか)、知識と所持、ブラウザの守りとアプリの守り。認証の設計力は、似ているものを区別する力です。
区別ができると、「なんとなく安全そう」が「どの攻撃に、どの盾が効いている」に変わるんですよね。
みなさんが見てきた認証まわりのヒヤリ、よかったら教えてください。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。