https://kurochan-note.hatenablog.jp/entry/2022/04/18/112307
昨年(2021年9月ごろ)に徳丸さんのこのツイートを見て、「2022年にはJWTを用いたセッション管理に代表される、ステートレスなセッション管理は世の中に受け入れられなくなっていくのだろうか?」と思っていました。
OWASP Top 10 2021 A1に「JWT tokens should be invalidated on the server after logout.」(私訳:JWTトークンはログアウト後にサーバー上で無効化すべきです)と書いてあるけど、どうやって無効化するんだ? ブラックリストに入れる?https://t.co/bcdldF82Bw
JWT大好きな皆さん、ここはウォッチしないとだめですよ。これがそのまま通ったら、ログアウト機能でJWTの即時無効化をしていないサイトは脆弱性診断で「OWASP Top 10 2021違反」と報告されてしまいますyo ! https://t.co/ltLb3Fd8mV
冒頭だけ読んで勘違いが広まるとよくないので、議論の結果最新版では方針が変わったということだけ先に書いておきます。詳細が気になる方は最後まで読んでみてください🙇♂️
OWASP Top10 2022の「A01:2021 – アクセス制御の不備」の日本語版では、2022年3月3日時点では以下のように書かれています。
JWTトークンはログアウト後にはサーバー上で無効とされるべきである。
この記述からは、ログアウト時にクライアントサイドでセッション(JWT)を捨てるだけでは不十分で、クライアント側がJWTを再利用すればサーバへのアクセスが成功してしまうのが問題であるということが読み取れます。 サーバ側で無効なJWTを管理しなければならないということは、JWTを利用したセッション管理に代表されるようなステートレスなセッション管理は認証の実装方法として不十分なのでしょうか?
こちらのIssueで議論がされていました。(徳丸さんのツイートよりも後に行われた議論のようです)
議論の詳細はここでは書きませんが、ここの議論からわかることをまとめます。
まず、JWT仕様を見る限り、OAuthをベースとしたOpenID Connectで使用することが想定された設計であることは明らかです。
OAuthには2つのトークンがあり、短命なアクセストークンと長命なリフレッシュトークンから構成されています。 それぞれのトークンがどんな形式であるべきかは指定されていませんが、アクセストークンにはJWTが使われている実装が多いようです。
アクセストークンの生存期間を短命にすることで、アクセストークンが不正に利用されるリスクを低減しています(リスクを低減しているのであって、完全に防いでいるわけではない)。この短命なトークンの実装としてJWTを使うことで、ステートレスな認証を実装することができ、データベースの負荷低減に寄与します。
その代わりにリフレッシュトークンはサーバサイドでの管理を必須とし、ユーザがログアウトするなどの操作を行うとリフレッシュトークンが即時無効化され、アクセストークンの更新はできなくなります。