世界を動かす技術を、日本語で。

JSON Web Tokenの10年と未来への準備

概要

  • JWT(JSON Web Token) が2015年5月に RFC 7519 として正式化
  • JWTを含む一連の JOSE関連RFC が同時公開
  • OpenID Connect との共同設計と幅広い用途での普及
  • 継続的な セキュリティ強化 とベストプラクティスの更新
  • 今後10年の進化と利用拡大への期待

JWTとJOSE標準の10年

  • 2015年5月、 JWT(JSON Web Token)RFC 7519 として標準化
  • 4.5年 に及ぶ設計・議論による成果
  • 同時に公開された JOSE関連RFC 一覧
    • RFC 7515: JSON Web Signature (JWS)
    • RFC 7516: JSON Web Encryption (JWE)
    • RFC 7517: JSON Web Key (JWK)
    • RFC 7518: JSON Web Algorithms (JWA)
    • RFC 7519: JSON Web Token (JWT)
    • RFC 7520: JOSEによる署名・暗号化例
    • RFC 7521: OAuth 2.0 Assertion Framework
    • RFC 7522: SAML 2.0 Profile for OAuth 2.0
    • RFC 7523: JWT Profile for OAuth 2.0
  • OpenID Connect との共同設計
  • 汎用性広範な採用実績 による成功
  • 「標準が成功した証は、想定外の用途でも使われること」という評価

JWTの普及と影響

  • JWT と関連仕様は、現代のオンラインセキュリティに不可欠な存在
  • OAuthOpenID ConnectJOSE コミュニティの貢献
  • 新たなユースケース業界標準 としての地位確立
  • 電話詐欺対策 など、想定外の分野でも活用

セキュリティ強化とベストプラクティス

  • 5年前に公開された JWT Best Current Practices(BCP)
    • 実運用 から得られた知見を集約
    • 落とし穴推奨事項 を明記
  • Yaron ShefferDick Hardt との共同でBCPを アップデート中
    • 新たな脅威対策 を追加
    • 最新版は JWT Best Current Practices specification で公開
  • Brian CampbellChuck Mortimore らと RFC7523bis も更新
    • トークンのaudience値の曖昧さ による脆弱性対策

今後への展望

  • John BradleyNat Sakimura との共同開発への感謝
  • OAuthJOSEOpenID Connect ワーキンググループの貢献
  • 今後10年 の進化と新たな活用分野への期待

Hackerたちの意見

標準が成功した証拠の一つは、発明者が想像もしなかった用途に使われることだと言われてるよね。それは確かに、何かの有用性や多様性の証だよ。おめでとう!

ハッカーニュースでJWTやOAuthに関する記事を探すと、何百ものコメントが循環論争をしてるのが見つかるよ。人々はこの二つを分けるのがなかなかできないみたい。

サーバー間でのJWTは好きだけど、サーバーとクライアント間だと結局クッキーやセッションを再作成することになるよね。あくまで私の経験/意見だけど、他の人の意見も聞きたいな。

一般的に、クッキーはドメイン間で再利用できないんだ。ブラウザがどのドメインにどのクッキーを送るかを制御してるからね。それに、クッキーは暗号的に署名されてないから、クライアントやブラウザによって簡単に偽造されちゃう。一方、JWTはドメインを越えて使えるから、あるドメインで発行されたIDPのJWTを別のドメインでも信頼できるんだ。暗号署名はデータの整合性を確認するのに役立つし、セッションは通常、一つのバックエンドやアプリケーションサーバーに結びついてるから、異なるアプリ間でセッションデータを再利用するのは難しい。でもJWTは異なるアプリサーバーやマイクロサービス間でセッションデータを共有できるんだよ。

クッキーはサーバーによってのみ制御されるけど、当然秘密を使って交渉することもできる。JWTは相互秘密のコンポーネントが組み込まれてて、かなりクールな感じだよね。だから、両方のエンドが相手を信頼して、JWTで証明する必要がある。クッキーが絡むと、運を天に任せることになるけど、相互TLSを使えばJWTが提供するのと同じ信頼を得られるよ。私が運用してるウェブアプリは両方使ってるんだけど、ウェブ開発者たちはJWTを主張して、ああ、認証ベアラーの部分を「忘れちゃった」みたいで、彼らのAPIでは使ってなかったんだ。結局、Apacheモジュールを修正して再コンパイルする羽目になったけど、次のバージョンでサポートするって言ってたから、私の変更を戻せるかも。今使ってるApacheプロキシのJWTモジュールでDBをちょっと調べれば、クレームが得られるよ。その前には、PrivacyIDEAインスタンスに対して認証が成功したときに生成されるApacheセッションクッキーがある。つまり、認証にはクッキー、認可にはJWTを使ってる感じかな。クッキーは両方できるけど、セッション以外はあまり詳しくないから、クレームを複数のクッキーで扱う必要があるように見えるけど、JWTは一つで全部できるんだよね。

JWTは好きだけど、複雑な認可ルールの強制が必要なシステム向けに、詳細でコンパクトな認可情報を伝えるためのより良い標準があればいいなと思う。かつて、JWTに権限を載せようとしたことがあったけど(人気のスコープよりも複雑)、それだとすぐに大きくなっちゃうんだよね。役割情報をJWTに載せる実験もしたけど、それだとロジックが再集中しちゃう。複雑な認可情報を一つのオブジェクトで何度も渡すのは根本的に欠陥のあるアイデアかもしれないけど、もしアイデンティティ標準のウィッシュリストがあったら、これが上位に来ると思う。

そうそう、トークンはすぐに長くなるよね。5年前にクライアントに役割を渡すために使おうとしたこともあったけど、いろいろ問題が出たんだよね。

認可は本当に一般的に解決可能な問題じゃないんだ。大きなシステムはそれぞれ独自のクセがあるし、一般化しようとすると痛みや苦しみ、そしてAWS IAMに繋がるんだよね。

Biscuitをチェックしてみるといいかもね。 > Biscuitは、分散型検証、オフラインの軽減、論理言語に基づく強力なセキュリティポリシー強制を持つ認可トークンだよ。 — https://www.biscuitsec.org

一度、JWTに権限を付与しようとしたことがあるけど(君の人気のスコープよりも複雑)、それだとすぐに大きくなっちゃう。ビットマスクを使うことで解決したよ。例えば、「カレンダーオブジェクトからの読み取りを許可する」というアクセスルールをエンコードしたいとする。典型的なCRUDアクションは4ビットでエンコードできる。例えば、すべてのビットがゼロなら→アクセスなし。最初のビットが1なら→作成可能。2番目のビットが1なら→読み取り可能。などなど。で、もしシステムに32種類のオブジェクトがあれば、「位置13はカレンダーをエンコードする」と言える。だから、32×4=128ビット、つまり32種類のオブジェクトに関するCRUDルールの情報をエンコードするのにたった16バイトで済む。確かに複雑に聞こえるけど、ライブラリに移せば考えなくて済むよ。

JWTはちょっと重すぎるし、JSユーザーはエンコーディングが暗号化じゃないことを忘れがちだよね。ニュースサイトのトラッカーがJWTをURLやヘッダーで第三者トラッカーに送るのを見たことがある。内容は驚くことじゃないけど、私のフルネームやメールアドレスが含まれてて、プライバシーポリシーに違反してるよ。他には、非常にオープンで便利で、JWTトークンを調べることで多くのサイトのアーキテクチャ設計について学べるんだ。

内容は驚くべきものではなく、私のフルネームとメールアドレスだよ。正しく記憶しているか分からないけど、これに関してはJWTに識別情報を保存しないことが推奨されているんじゃなかったっけ?

JWTは署名されてるけど、署名は暗号化とは違うんだよね。でも、リンク先の記事で言及されてるJWEもあるよ。これは完全に暗号化されてる。

tptacekの調査はここでも言及されたけど、もっと有名になるべきだと思う。https://fly.io/blog/api-tokens-a-tedious-survey 残念ながら、業界の99%はどのトークンを使うかをMediumの記事やLLMの回答、NPMで見つかるメンテされてないパッケージの数で決めてるみたい。JWTは主にアクセストークンとして使われるけど、大多数のユースケースには合わないんだよね。トラフィックが少なくて厳しいマルチリージョンのデプロイ要件がなければ、ランダムIDがベストなアプローチだよ。すごく軽量で、取り消しも簡単だしね。結構安全だよ。このアプローチで思いつく一般的な脆弱性はセッション固定攻撃[1]とタイミング攻撃[2]くらいかな。これらの攻撃は、ちょっとした予防策を取れば防げるよ。1. 認証時に暗号的に安全な乱数生成器を使って、常に32バイトのセッションIDを生成すること。(新しいログインのために既存のセッションIDを再利用しない)2. セッションをクエリする際に使用するデータベースフィールドにセッションIDの暗号ハッシュ(例:SHA-256やBlake2b)を使うか、セッションIDフィールドがハッシュベースのインデックスでインデックスされていることを確認すること(B木はタイミング攻撃に弱いからね)。もし本当にセッションIDが使えない場合は、サービスが大きくて重要なものであれば、カスタムProtobufトークンやMacaroonsのような特別な形式を使うべきだよ。これらの形式はもっとコンパクトで、自分のニーズに合わせて設計するための完全なコントロールを提供してくれる。たとえば、柔軟なクレーム(ほとんどがサービス間で標準化されている)を持ち、暗号化もしたいなら、Protobufとlibsodiumのシークレットボックスエンベロープの組み合わせを使うといいよ。[1] https://owasp.org/www-community/attacks/Session_fixation [2] 例:https://github.com/advisories/GHSA-cvw2-xj8r-mjf7

JWTを使おうとするたびに、最適な選択肢じゃない気がするから、実際のユースケースを見つけたことがないんだ。最近、TOTPを使った2FAを実装したいと思ったんだけど、セッション用に1つのクッキーを使って、もう1つのクッキーをTOTPバイパス用に使おうと思ったの。もしユーザーが2FAバイパスクッキーを持ってなければ、2FAチャレンジをクリアしなきゃいけない。いい感じだよね。ユーザーは通常通りにユーザー名とパスワードを送信するけど、通過してもバイパスクッキーがなければ、サーバーは10分の有効期限付きJWTを返す。ユーザーはログインを完了するためにJWTとOTPを返さなきゃいけない。これでOKだと思うけど、最適ではないかな。最悪のケースだと、ハッカーはユーザー名やパスワードを送信せずにJWTを偽造しようとする。ユーザーIDはJWTに平文で含まれてるけど、鍵はサーバーにしか存在しないから、割と難しいと思う。ただ、クライアントは無限に試行できるから、JWTはステートレスで、有効期限を延ばしたり、未来の遠い日時に設定したりできる。まあ、256ビットだから、成功する可能性は低いけど、何が起こってるかには注意しておくべきだと思う。代替案?成功したユーザー名/パスワードの組み合わせごとにユニークな2FAチャレンジキーを作成すること。ユーザーはチャレンジキーとOTPを送信する。同じ256ビットのセキュリティだけど、各ログイン試行ごとにユニークで、グローバルHMACキーを使う代わりにね。また、試行回数を約3回に制限するのも簡単だし、ハッキング試行の記録も残せる。明らかに良い感じだね。ストレージはあまり心配じゃないけど、最悪の場合、10分以上古いキーはすべて削除できるから。欠点はDBにアクセスしなきゃいけないことだけど、それは非常に効率的なクエリだし、ボトルネックになったらキー・バリューストアに移行することもできる。どうなんだろう、ユースケースは何?サーバー間のやり取り?それなら、JWTを検証するために鍵を共有する必要があるし、ユーザー向けのサーバー以外は公共のインターネットにさらす必要もないと思うから、なんでそんなにJWTを追加する必要があるのか理解できない。あまり詳しく調べてないけど、マイクロサービスアーキテクチャにはあまり賛同してないから、もしその道を進むなら、gRPCやprotobufを試して、JWTにはあまりこだわらないと思う。

JWTにはクレームが含まれることができるのが違いだね。JWTは最初からちょっと複雑なデータ構造なんだ。認証と認可を一度にできるし、個別のブラウザクッキーを使ってもできるけど、めんどくさいよね。でも、セッションクッキーをデータベースに保存して、サーバーでローカルにクレームを処理して、そのクッキーを使って全部つなげることもできる。だから、どちらの方法でもできると思うよ。JWTは相互認証(共有シークレット)だけど、クッキーはそうじゃないからね。

あなたのシナリオでは、偽造されたJWTを送信する試行がX回検出された後に、ユーザーIDに追加の保護を適用することもできるよ。少なくとも、無効な署名のJWTが届いたら警告を出すことができるし。JWTの中に2FAのチャレンジキーを入れることもできるし、JWTを情報を保持するコンテナとして使えばいいんだ。JWTはクッキーができること以上のことをするわけじゃないと思うけど、アプリ向けの使い方だと思う。特に、生のHTTP APIコールを行ってクッキージャーを実装していないアプリにね。それで、ほとんどの企業が「アプリファースト開発」をしているから、結局ウェブブラウザでもJWTをサポートしなきゃいけなくなって、手動でローカルストレージやアプリケーションの状態に入れる羽目になってる。最近、JWTを使ったSSOソリューションを実装しなきゃいけなかったんだけど、プラットフォームがJWTしか出さなかったから、JWTを暗号化されたHttpOnlyクッキーの中に入れることになった。ちょっと無駄な感じもしたけど、まあいいか。

JWTが存在するずっと前、信頼できないチャネルを通じて信頼できるデータを渡したい場合、期限付きのペイロードを作って、秘密鍵で暗号化または署名して送信してたんだ。でも、その情報を送る方法は自分で考えなきゃいけなかった。例えば、これがウェブサイトだったら、署名された/暗号化されたペイロードをいくつかのフォームフィールドに入れて、受け取ったときに自分の鍵で署名を確認する感じ。今はJWTがあるから、標準的な方法があって、同じつまらないコードをいろんな言語で何度も書く必要がなくなった。1つのフィールドに渡す1つの文字列があればいいし、誰かにそれがJWTだと言えば、どうやって解析すればいいか知ってる。もう自分の特別な方法を文書化する必要もない。結局のところ、以前は標準的な解決策がなかった特定の問題のための標準に過ぎないんだ。もしそんなデータの渡し方があなたのユースケースに問題がないなら、そのツールは必要ないよ。Protobufの例を使うと、Protobufやそれに似たツールが存在する前の時代もあった。Java、PHP、Pythonで同じプロトコルコードを手で書くのは本当に面倒な作業だよ。でも、自分のプロトコルを書く必要がなかったら、手動でやる苦痛もProtobufを使う楽しさも知らないだろうし、それでいいんだ。

使い道は? JWTの使い道としていつも思い出すのは、「サーバーレス」ブームの一部だったこと。理論はこうだった:JWTを使うと、認証に関してアプリケーションロジックがステートレスになるから、セッションデータベースやKVストアからユーザー情報を読み込む必要がなくて、リクエストの中にその情報がある… これが意味を持つのは、アプリケーションが自分のストレージをまったく持っていない場合だけだと思う。すべてリモートAPI/サービスで、認証ソースも含めてね。そういうアプリケーションは確かにあると思うけど、ほとんどの場合がそう使われているとは信じがたい。新しいものに夢中になるこの業界の能力を過小評価しちゃいけないよ。数年前、若手の開発者と一緒に働いていたときに目から鱗が落ちる経験をしたんだ(その時は自分の方がかなり経験豊富だったけど、「シニア」とは呼べなかった)。彼は私たちが働いていたエージェンシーのために内部ツールを作ったんだけど、具体的な詳細は覚えていないけど、会計士も関わっていて、かなり基本的なCRUD系のPHP/MySQLアプリだった。特に目立つものではなかったけど、ちゃんと動いてた。ある時、彼はPHP/MySQL環境の設定に問題があったみたいで(新しいノートパソコンで?)、Dockerが普及する前の時代だったし、Vagrantはすでにあったかもしれないけど、彼は使ってなかった。彼が後で説明してくれたところによると、「localhost」に接続するとMySQLクライアントがソケット接続を試みる非常に一般的な問題だったみたいで、PHPに提供されるデフォルトのソケットの場所が常に正しいわけじゃないんだ。彼はその接続の問題があったとき、すでにうまく動いていたアプリをMongoDBを使うように全部書き直す必要があると決めたんだ。だから、やっぱりこの業界が新しいものに夢中になる能力を過小評価しちゃいけないよ。

トークンIDを保存するために使えるjtiクレームがあるから、サーバー側で発行されたトークンを追跡することができる。256ビットをブルートフォースで解読するのは、君が言ったように現実的にはあり得ないし、その計算によって侵害されるシステムもたくさんあるから、孤立したJWT署名は非常に特定の例に見える。僕にとってJWTの良い点は、非対称署名と検証ができるところ(IDトークン)。

うーん、ユースケースは何なの?サーバー間のやり取り?それなら、JWTを検証するためにキーを共有する必要があるよね。おそらく、ユーザー向けのサーバー以外は公開インターネットにさらす必要もないし、なんでわざわざJWTを追加するの?サーバー間でのJWTは通常、署名と一緒に使われるし、HMACモードではないから(つまり、グローバルに共有されたHMACキーはない)。それで、発行者は下流の利用者のためにJWKSエンドポイントを公開するだけだから(公開鍵を配布するための追加のメンテナンスは不要)。

HNの伝説からの前提: https://fly.io/blog/api-tokens-a-tedious-survey/

JWTに関して僕が抱えてる問題は、実際にはユーザーID以外の情報が長期間有効だと仮定できることはほとんどないってことかな。最もシンプルなクライアント認証のケースでは、アカウントが侵害されたらすぐに認証を取り消せるようにしたいよね。つまり、リクエストごとに認証データベースをチェックしなきゃいけないし、他のクレームの情報もそこで素早く取得できたかもしれない。役割についても同じで、管理者ユーザーを下位の「クラス」にダウングレードしたら、すぐに反映されるようにしたい。だから、結局残るのは統一されたクライアントIDフォーマットだけで、これは多少役に立つけど、JWTの「約束」とは言えない気がする。

最もシンプルなクライアント認証のケースでは、アカウントが侵害されたらすぐに認証を取り消せるようにしたい。つまり、リクエストごとに認証データベースをチェックしなきゃいけないし、他のクレームの情報もそこで素早く取得できたかもしれない。ちなみに、以前にこの「アクセスごとにDBをチェックして取り消しを確認する」問題をうまく回避するシステムを作ったことがある。重要なポイントが二つある。1. 取り消し(または通常は「明示的なログアウト」)は、多くのユーザーアプリケーションパターンでは実際にはかなり稀だってこと。例えば、多くのウェブアプリではユーザーが明示的にログアウトすることはほとんどない。モバイルアプリではさらに稀だ。2. トークンの有効期限が切れるまでの間だけ、取り消しリストを保持しておけばいい。例えば、トークンの有効期限が30分で、正午にユーザーのトークンを無効にしたら、12:30にはその取り消しステートメントを削除できる。なぜなら、その取り消しの影響を受けたトークンはすでに期限切れになっているから。だから、比較的短いトークンの有効期限(例えば30分)であれば、トークンの有効期限リストはほぼ常にメモリに収まる。僕が作ったものは、1. トークンが期限切れかどうかを確認するインターフェースは基本的に「getEarliestTokenIssuedAt(userId: string): Date」で、特定のユーザーに対して有効と見なされるトークンの最も早い発行タイムスタンプを取得するもの。だから、ユーザーの以前発行されたトークンを取り消すには、この日付をNow()に設定するだけで、それ以前に発行されたトークンは無効と見なされる。2. PostgresにユーザーIDと最も早い有効トークンの日付を保存するテーブルがあった。ただ、PostgresのNOTIFY機能を使って、このテーブルに行が追加されるたびに全サーバーにブロードキャストを送信していた。3. サーバーにはこのテーブルのローカルコピーがメモリに保存されていた。再度言うけど、最も長いトークンの有効期限を超えたエントリーは削除できるから、メモリに収まる。万が一、現在の取り消しリストがメモリに収まらない場合は、「メモリがいっぱい」と言える仕組みを作って、Postgresにコールバックするようにした。ただ、その状況は数分後には取り消しが減ってトークンの有効期限が過ぎると自然に解消される。これ、実際には思ったより複雑じゃなかった。メリットは、1. ほぼ状態を持たないから、スケーラビリティに優れていること。2. トークンの検証はほぼ常にメモリで行えること。数年間このシステムを運用してきたけど、メモリ内の取り消しリストが大きくなりすぎたことは一度もなかった。

アクティブなユーザーログアウトや削除、権限変更は稀だから、取り消しリストのサイズは存在するトークンの数に比べて非常に小さい。取り消しを非常に高速なルックアップシステム(例えばブロードキャスト+メモリストア)に保持して、5〜60分の比較的短いトークン更新と組み合わせれば、トークンの有効性チェックの回数を大幅に減らせるし、認証システムのダウンタイムにも耐えられる。これは、認証データが他のデータと同じDBにある基本的なアプリにはあまり関係ないけど、大きなシステムではそうなることは稀だ。

[フラグ付き]

君は視野が狭いと思うよ。例えば、メールで送られるマジックリンクはかなり長い有効期限を持つことができる。

トークンがJWTじゃないなら、ほんとに「ベアラートークン」なの?

最もシンプルなクライアント認証状態のユースケースでは、アカウントが侵害されたらすぐに認証を取り消せるようにしたいよね。つまり、リクエストごとに認証データベースをチェックしなきゃいけないし、クレームにあった他の情報もすぐに取得できたはず。君のシナリオがJWTにどれだけ関係してるのか、全然分からないよ。君のフラストレーションは理解できるけど、それはJWTとは関係ないよ。自分が書いたことをちょっと読み返してみて:アカウントが侵害されたら、攻撃者はその瞬間から認証情報を悪用し始めるんだ。攻撃者が有効な認証情報を手に入れた瞬間が、君が攻撃を発見した瞬間じゃないし、ましてやそのアカウントを強制的にグローバルサインオフさせた瞬間でもない。つまり、君のシナリオでは悪用を防げないってことだよ。すでに悪用されているトークンを取り消してるだけなんだから。あと、リソースサーバーでJWTベースのアクセス制御を実装した身としては、取り消しリストをチェックするのは基本的なシナリオだよ。これは非常に基本的で速いエンドポイントとして実装されることが多いし、JWT IDのリストを提供するんだ。リソースサーバーはこのエンドポイントをポーリングして変更をチェックし、JWTチェックの一環として毎回リストを確認する。トークンを取り消してから、そのトークンをリクエストで拒否するまでの時間は、エンドポイントをどれだけ頻繁にポーリングするかで決まるよ。1秒が長すぎると思う? > ロールについても同じことが言えるよ。管理者ユーザーを下位の「クラス」にダウングレードしたら、すぐに反映されるようにしたいよね。全く同じシナリオだよ:クライアントにアクセス・トークンを更新させて、発行されたトークンを取り消す。やっぱり、1秒が長すぎるの? それに、JWTにロールを含める必要はないからね。OAuth2はそうじゃないし、リソースサーバーがjtiを使って別のサービスからロールを取得するのを妨げるものはないよ。それでも、そのサービスがトークンの取り消しよりも早く更新されると思う? > だから、残るのは統一されたクライアントIDフォーマットだけで、まあそれなりに便利だけど、JWTの「約束」とは言えないよね(私の感覚では)。OAuth2はそれだけだよ。OAuthに何か問題があるの?それに、君はJWTの本質を完全に見失ってるみたいだね。JWTの最大の特徴は、リソースサーバーが外部サービスを使わずにローカルでアクセス・トークンを検証できることなんだ。トークンの取り消しやグローバルサインオフはよく問題視されるけど、こういうシナリオはあまり頻繁に起こらないし、実装も簡単だからね(エンドポイントを定期的にポーリングすることは、あまり変わらないよ)。

侵害されたトークンについてのランダムなアイデアがあるんだけど、あまり意味がないかも。クライアントのIPアドレスみたいなものをトークンに入れたらどうかな?そうすれば、サーバーは異なるIPアドレスからのリクエストを受け取った瞬間に拒否(そして侵害としてマーク)できるんじゃないかな?でも、DHCPや無線LANで大きな建物の中を移動する人には無効になっちゃうことも理解してるよ。

大規模な侵害があった場合は、新しいキーを展開すればいいだけだよ…現在のすべてのJWTを無効にして、新しいログインを強制することになるし…ユーザータイプごとに署名キーをグループ化して、リフレッシュを最小限に抑えることもできるよ。

アカウントが侵害された場合、すぐに認証を取り消せるようにしたい それはシステムによるね。私の経験では、アクセスを取り消したいアプリはたくさんあるけど、それを透明な再認証と天秤にかけてる。OIDCはこれをうまく処理してて、* 短いアクセストークン/IDトークンの有効期限(数秒から数分) * 定期的な透明なトークンのリフレッシュ(数日から数ヶ月有効なリフレッシュトークンを使う) こういう柔軟性があるから、開発者は銀行向け(アクセストークンとリフレッシュトークンの有効期限が短い)と消費者向けアプリ(アクセストークン/IDトークンの有効期限が短く、リフレッシュトークンの有効期限が長い)で同じ技術を使えるんだ。

最近のJWTの意味があんまりわからないな。SameSiteやCSPヘッダーがあるし、バックエンドの視点から見ると、ほとんどのフレームワークにはクッキーでセッション追跡が組み込まれてるから、クライアントを一つか全部簡単に無効にできる。だけどJWTの場合、そんなのはほとんど存在しないし、クライアントを追跡するためにセッションの仕組みを再実装しなきゃいけない。

SameSite/CSPヘッダーとJWTは互いに無関係だよ。私はJWTシステムを使って、RESTバックエンドに対してSPAを認証してるけど、JWTはクッキーに保存してる(SameSite=strictとHttpOnlyを使って)。

10年分のツールの苦痛って感じだね。どんな良い解決策があるのか分からないけど、OAuthやJWTの設定を扱うのは本当に面倒くさいよね。技術スタックに関係なく。

数年前のアイデンティティカンファレンスでの面白い動画があるよ。スピーカーはJWTの仕様の著者の一人、ブライアン・キャンベル。https://www.youtube.com/watch?v=IgKRGS6cQWw 動画の説明はこうだよ:> JWTはIETFの標準セキュリティトークン形式で、シンプルさとライブラリの広範な入手可能性から、近年非常に人気がある。しかし、その人気にもかかわらず(あるいはそれが一因で)、JWTは情報セキュリティの信頼できる人々から厳しく批判されてきた(「ひどい標準」、「RFCは猿が作った」、「インターネットの最悪の暗号標準」、「JWTは災害...どれだけひどいか驚き」、「単純で複雑で危険が同時にある」、「安全なJWTライブラリを構築するのはほぼ不可能」...こういった感情がある)。> この批判は、ライブラリやデプロイメントにおける公然の脆弱性の流れによって裏付けられ、拡大されてきた。実際、JWTには深刻で正当なセキュリティ問題があり、その多くは仕様自体の根本的な欠陥に起因していて、それが実装ミスを許可したり、さらには奨励したりしている。しかし、JWTは取り返しのつかない欠陥を持っているのだろうか?このセッションでは、その問いに真剣に取り組み、JWTの基本をレビューし、最も一般的であるいは痛烈な批判と関連する実世界の脆弱性について実用的に見ていく予定だよ。