Upgrade to Pro — share decks privately, control downloads, hide ads and more …

認証認可を通して学ぶ、『わからない』のつぶし方(仮) - ID沼入口 発表資料

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for calloc134 calloc134
June 27, 2026
23

認証認可を通して学ぶ、『わからない』のつぶし方(仮) - ID沼入口 発表資料

“ID沼入口” - 基本とセキュリティから始める、考え続けるためのID管理技術勉強会 で発表を行う資料です。
現在作成中のため、変更のある可能性があります。

https://openid.connpass.com/event/396041/

Avatar for calloc134

calloc134

June 27, 2026

More Decks by calloc134

Transcript

  1. かろっく @calloc134 右下の QR からプロフィールへ → 自己紹介 Web アプリとセキュリティ が好きな社会人一年生

    フロントエンドは React + TypeScript バックエンドは Hono などをよく触る。最近はお仕事でGoやPHP インフラは少し。メインPCはLinux、家のルータはOpenWrt 基本的にWebアプリ・クラウドネイティブ・コンテナ周りに興味がある 認証認可・Web セキュリティの沼 に片足を突っ込み中 コードリーディングを楽しむ人 (ReactやPostgreSQL) @calloc134 2
  2. S E C T I O N / 0 1

    OAuth/OIDC 仕様の 学習の難しさ @calloc134 5
  3. 関連仕様が多く全体図が見えない OAuth 2.0 だけでも いきなり仕様を読むと心が折れがち ※ 余談: 重要な仕様は OAuth 2.1

    として集約が進んでいる 仕様が多い RFC6749 OAuth 2.0 RFC9700 OAuth 2.0 Security BCP RFC6750 Bearer Token Usage RFC7636 PKCE … @calloc134 7
  4. ある概念を理解するために 別の仕様を前提 としていることが多い 例: 「Q. 認可コードフローは何故認可コードを挟むのか?」 前提となる知識 ここまで履修してようやく最初の質問に答えることが出来る 依存関係の複雑さ (1)

    Implicit Flow の存在 Confidential Client / Public Client の違い フロントチャネル露出のリスク PKCE の存在 トークン交換をどう結びつけるか Implicit Flow だと PKCEを挟み込む余地がないこと @calloc134 8
  5. 特に、フロントエンド界隈の人間が目にしがちな実装 初学者目線だと 実はこの実装は結構クセのある用法 。いきなりラスボスに挑むようなもの 更にこの構成を「普通だ」と思ってしまうと、本来の用途の理解の妨げ にもなる 現実世界の身近な実装のわかりづらさ Auth0 や Firebase

    などの IdP を利用 フロントエンドからアクセストークンを取得 フロントエンドからバックエンドにアクセストークンを渡す アクセストークンを使ってログイン状態を管理 技術上は OAuth だが、リソース認可ではなくログイン用途に見え 混乱する Public Client で動作するが、初学者がいきなり Public Client を考えるのは難しい @calloc134 10
  6. S E C T I O N / 0 2

    認証認可プロトコル学習のコツ @calloc134 12
  7. 最初から実務の構成で理解しようとすると、混乱する OAuth の素直な例 → リソースに対する認可 例: Googleフォトに保存している写真を、印刷サービスに渡す OIDC の素直な例 →

    外部サービスのユーザ情報を用いたログイン(ID連携) 例: Googleアカウントで別サービスにログインする 想定するアプリは Rails のような サーバ上で動作する Web アプリケーション が良い フロントエンドがなく、Confidential Clientとなり OAuth/OIDC の本質に集中 できる ひねくれてない例から理解する (1) @calloc134 13
  8. 一から学習するのにおすすめのルート (もちろん復習にもおすすめ) 学習のルートを工夫する (1) OAuth の登場人物を理解する 1 OAuth の素直な例を理解する 2

    ここで考えないこと 認可コードフロー以外のフロー Confidential以外のクライアント どういう攻撃があるのかを理解(一周目) 3 認可リクエスト側 トークンリクエスト側 ここでPKCEがようやく登場 @calloc134 15
  9. このルートなら、循環参照が比較的発生せず、つまづきにくい 学習のルートを工夫する (2) クライアントタイプの違いを理解する 4 Confidential / Public Publicに対する攻撃を理解する(二周目) 5

    認可コードフロー以外のフローを理解する 6 Implicit Flow ここでようやく、非推奨の理由が理解できる OIDC に進む 7 アクセストークンとIDトークンの用途の違い JWTに関する仕様 後は OAuth と同じように認可コードフローを辿る @calloc134 16
  10. 無意識のわからないからくる違和感を 「モヤモヤ」 と呼んでいく まずモヤモヤを質問の形に変換して吐き出せるかどうか が、わからないを潰す上で重要なポイント 例: 「認可コードフローってなんかややこしくない…?」 モヤモヤ… → 「モヤモヤ」から質問をうまく言語化できた

    この作業は難しいので、繰り返して慣れるしかないかも… まず「モヤモヤを吐き出す」をうまくなる なんでモヤモヤするんだろう? 1 登場人物が多いから?それとも矢印が多く見えるから? 2 なんでこの矢印が多いんだろう? 3 認可コードが挟まってるからかな? 4 「アクセストークンをそのまま返せばよいのでは?」 5 @calloc134 18
  11. おすすめ: GPT 5.5 Extended Thinking の Web検索 個人的な感触だと ChatGPT Plus

    を契約して質問しまくるのが一番確実 質問の答えだけでなく、「モヤモヤを言語化する」というプロセス自体の練習になる AIの回答は鵜呑みにしすぎないこと! 必要に応じて仕様で裏取りすること はやはり重要 わからないの潰し方(1): とりあえずAIに質問する @calloc134 19
  12. S E C T I O N / 0 3

    仕様をもとに読み解く リアルワールド実装 @calloc134 23
  13. Hono JWK Middlewareにおいて CVE-2026-22818 として報告された脆弱性 alg パラメータのない JWK が存在した場合 ユーザがJWTの

    alg を指定でき、任意のJWTを偽造できてしまう という脆弱性 ※ 実際は WebCrypto の importKey() がエラーで落ちるので悪用は確認されず (1) Hono JWK Middleware の脆弱性 @calloc134 25
  14. 根本原因は、ユーザから渡される JWT の alg を信頼してしまっていたこと → alg にホワイトリスト形式を採用し、フィルタリングを行うことで解決 JWTの alg

    は、実はユーザが指定できるパラメータ 扱い 外界からの入力 であり、信頼してはいけない しかしこの感覚は、仕様の意図まで深く理解していないとなかなか気づけない難しい部分 JWK Middleware の脆弱性の原因 alg を見てアルゴリズムを決定 1 この時点では署名検証は行われていない ユーザが指定したアルゴリズムで署名検証を行う 2 @calloc134 26
  15. フレームワーク側の脆弱性ではないが、OAuth/OIDC の深い理解が必要 な設定ミス問題 IdP + SPA + バックエンドAPIの構成で、 バックエンドAPIがJWTのaudを検証していない場合、異なるAPIへのJWTでもAPIアクセスが出来てしまう という問題

    (攻撃者が作成した別アプリ用のJWTでも受け入れるため、攻撃者のアプリにログインしたユーザになりすますことが 出来る) ※ 実際は多くのIdPでテナント分離されているので一定の保護はされるが 同一テナントの場合は危険 (2) Hono JWT Middleware の設定ミスによる問題 @calloc134 27
  16. JWT Middlewareの設定に aud の検証を行うオプションを忘れると発生 → JWTで aud を検証していなければ 攻撃者の作成した別アプリAPI用のJWTでも受け入れてしまう ことに

    JWT Middleware の設定ミスの原因 aud : JWT形式のアクセストークンにおいて、どのリソースサーバ向けのトークンかを示すパラメータ IdP + SPA + バックエンドAPIの構成では バックエンドAPI = リソースサーバ つまり aud = バックエンドAPIの識別子である必要がある @calloc134 28
  17. そもそも IdP + SPA + バックエンドAPIの構成で、アクセストークンをセッション代わりに使うのは 良くない そもそもこの構成は良くない 慎重に扱わないと今回のように JWT検証の設定ミスによる脆弱性

    が発生する SPAがOAuthクライアントとして動作するため、Public Client 扱い しかし OAuthでは出来るだけ Confidential Client を使うことを推奨 この用法は「APIリソースを認可する」というより 「外部のアカウント情報を連携してバックエンドAPIにログインする」ためにOAuthを利用している この用途ならそもそもID連携用に作られた OIDC の IDトークンを使う方が適切 @calloc134 29
  18. より良い解決策: バックエンド側APIで OIDC の IDトークンを検証しログイン実装 SPA と APIの通信は アクセストークンではなく httpOnlyなセッションCookie

    を使う ※ 余談: セッションCookieを利用するため、CSRF対策は必須 じゃあどうすべき? 認可のためのOAuthではなく ID連携のためのOIDCを使う → より意図に沿った選択 Public Client ではなく Confidential Client を使う → より安全な構成 SPAとAPIの通信はアクセストークンではなく httpOnlyなセッションCookie を使う → 悪性なスクリプトからのアクセスを防ぐ (副次的効果) @calloc134 30
  19. S E C T I O N / 0 4

    まとめ @calloc134 32