Slide 1

Slide 1 text

Web アプリ認証の全体像 2026/06 北野 佑一

Slide 2

Slide 2 text

自己紹介 名前 北野 佑一(Kitano Yuichi) 部署 クラウド事業統括本部 コンサルティング1部 モダンアプリコンサルティングチーム 好きなAWSサービス Amazon Cognito AWS CLI 2

Slide 3

Slide 3 text

この勉強会で持ち帰ってほしいこと Webアプリに認証機能を入れるための「地図」を頭に入れるのが目的。 ライブラリの使い方ではなく 判断基準 を持ち帰る 細かなプロトコル詳細より 位置づけ を優先する 前提(構成)が変わると、認証の「正解」も変わる 3

Slide 4

Slide 4 text

アジェンダ 第 1 章 認証とは何か 第 2 章 [状態維持] Web ブラウザの状態維持 第 3 章 [状態維持] トークン認証 / JWT 第 4 章 [手段] 認証の 3 要素 第 5 章 [手段] パスワード 第 6 章 [手段] 多要素認証(MFA)& パスキー 第 7 章 [委譲] ソーシャルログイン & SSO 第 8 章 実装の選択肢 第 9 章 まとめ 認証の話ですがスルーされがちだけど前提として大事な 状態維持。 手段より先に、状態維持の話を手厚く進めます 4

Slide 5

Slide 5 text

第 1 章 認証とは何か そもそも認証とは何か、何のためにあるのかを揃える 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 6

Slide 6 text

認証 と 認可 6 認証 (Authentication) 「あなたは 誰 か?」 👤 ユーザー 🔒 サーバ 認可 (Authorization) 「何をしてよい か?」 🔒 サーバ 👤 Alice パスワード ✅ 本⼈確認 OK を開きたい 🔎 Alice は admin 権限を持つ? あなた = Alice さん と確定 ✅ 許可 or ❌ 拒否 例) ID/PW、パスキー、ソーシャルログイン 例) ロール、ACL、属性ベース (ABAC) ID + ↓ /admin ↓ 認証(Authentication)= 「相手が誰であるかを確かめる」行為。 Web アプリでは、サイトを訪れたユーザーが「アカウントを持っている 本人 なのか」を判定する 仕組みを指す。 認可(Authorization) = 「あなたは 何をしてよいか」

Slide 7

Slide 7 text

なぜ Web で認証が必要か リクエストごとに「これは 誰の操作か」を都度確かめる必要がある サイトを訪れただけでは「本人」と確定しない 認証は Web アプリの ほぼ全機能の前提 7

Slide 8

Slide 8 text

用語の地図:認証の定義 +実装の 3 観点 8 「認証」を 1 語で混ぜず、メタ概念(認証とは何か)と 実装の 3 観点(状態維持/手段/委譲) に切り分けます 🔑 認証とは何か(メタ概念)|第 1 章 「相⼿が誰であるか」を確かめる⾏為 ── 認可(何をしてよいか)とは別物 実装するときの 3 つの観点 状態維持|第 2〜3 章 問い ログイン状態をどう持続させるか 代表例 ・Cookie + セッション ID ・JWT(短命)+ Refresh Token ※ ⼿段|第 4〜6 章 問い 何を使って本⼈だと証明するのか 代表例 ・パスワード ・TOTP / SMS ・パスキー(WebAuthn) 委譲|第 7 章 問い 認証を他者(IdP)に任せるには 代表例 ・OIDC(ソーシャルログイン) ・SAML / SSO 認証で⼀括りにせずメタ概念と 3 観点を混同しないことが理解の第⼀歩

Slide 9

Slide 9 text

実装の3 観点はどう絡むか 9 手段 はログイン時の 1 回/状態維持 はその後の毎リクエスト/委譲 は手段の置き場所を外に出す フェーズ 1:ログインの瞬間(1 回だけ) 経路 A:⾃アプリで認証する ユーザー 経路 B:認証を IdP に委ねる 【委譲】 【⼿段】 IdP 【⼿段】 パスワード/パスキー等を検証 IdP 側で検証 (Google / Cognito 等) 認証ロジックを⾃分で持つ 認証成功 ⾃アプリは結果(ID Token 等)を受け取るだけ ⾃アプリがセッション ID/トークンを発⾏ Set-Cookie / レスポンスボディ等で渡す フェーズ 2:ログイン後(毎リクエスト) 【状態維持】 毎回 Cookie / Authorization ヘッダで セッション ID/トークンを送る ブラウザ ⾃アプリ 検証 OK ならレスポンスを返す(再認証は不要) この帯の中で「⼿段」は登場しない。 トークン⽅式のみ:期限切れになったら refresh_token で新しいトークンを取得 発⾏済みの ID/トークンを使い回すだけ。 (再認証は不要 / 第 4 章で詳述)

Slide 10

Slide 10 text

第 2 章 [状態維持] Web ブラウザの状態維持 ログイン「手段」(パスワードや MFA)の前に、まず認証を維持する仕組み(セッション・ Cookie)から押さえる 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 11

Slide 11 text

HTTP のおさらい 1 どこへ (https://example.com/) ① リクエスト メソッド: 何をしに (GET/POST) ヘッダ・ボディ: ついでの情報 URL: 🌐 ブラウザ ⚙ サーバ : 200 OK / 404 / ... ② レスポンス ステータス ヘッダ・ボディ: HTML / JSON など 1 往復 = 1リクエスト + 1レスポンス クライアント(ブラウザやスマホアプリ)とサーバの 1 回のやり取り = 1 リクエスト + 1 レスポ ンス。 リクエストは「どこへ(URL)」「何をしに(GET/POST)」「ついでに渡す情報(ヘッダ・ボディ)」 で構成される。

Slide 12

Slide 12 text

ステートレスとは 2 🌐 ブラウザ ⚙ サーバ ① POST /login(ID・パスワード) ✓ ようこそ A さん ② GET /mypage(次のページ) 🤔 あなた誰ですか?(① を覚えていない) ③ GET /orders 🤔 あなた誰ですか? リクエスト 1 回ごとに独⽴に処理 = ステートレス HTTP は仕様上、ステートレスでリクエスト 1 回ごとに 独立 している。 何の工夫もしないと「次のページを開いた瞬間に他人」になる。

Slide 13

Slide 13 text

状態を持たせる仕組み =Cookie 3 ステートレスな HTTP に「状態」を持たせるために生まれたのが Cookie。サーバがブラウザに預 ける 小さなメモ で、ブラウザは同じサイトへのリクエストに毎回 自動で 添えて返す。 認証専用ではなく、サイト側が覚えておきたいことを預ける 汎用の仕組み 例: 言語設定、カートの中身、そして「ログイン中」という状態 🌐 ブラウザ ① POST /login (id, pw) ⚙ サーバ ② Set-Cookie: session=abc123 🍪 保存 ③ GET /mypage + Cookie: session=abc123 (⾃動付与) 🍪 読込 ④ 200 OK (Alice⽤ページ) ブラウザが Cookie を ⾃動で リクエストに乗せて運ぶ

Slide 14

Slide 14 text

Cookie を使って実装する概念 =セッション 4 「ログイン中」という状態も Cookie で持たせたい。ただし Cookie に ユーザー情報をそのまま入 れるのは NG。改ざんも盗み見もできてしまう。 そこで Cookie には 手がかり(セッション ID)だけ を入れる 本体のデータは サーバ側 に置き、リクエストのたびに ID で引き当てる この「Cookie + サーバ側データ」の組み合わせの仕組みを (Web)セッション と呼ぶ 🌐 ブラウザ側 🍪 Cookie session_id= 🔑 鍵だけを持つ 意味のないランダム⽂字列 (連番は厳禁 — 推測される) 🗄 サーバ側 セッションストア 鍵で照合 session_id a1b2c3... x9y8z7... ... ユーザーデータ user_id=Alice role=admin user_id=Bob role=user ... 🔓 本物の情報 メモリ / DB / Redis などに保存 ブラウザには 鍵だけ 、本物はサーバ側ストアにある

Slide 15

Slide 15 text

セッションストアの選択肢 メモリ 一番手早い 再起動で消える 複数台で共有不可 RDB 永続化される 複数台で共有OK 読み書きが多く遅い 5 Redis 等 メモリDBで高速 複数台で共有OK Web アプリの定番

Slide 16

Slide 16 text

ログインの1 往復の例 👤 ユーザー 6 🌐 ブラウザ ⚙ サーバ 🗄 セッションストア ① ID + PW を⼊⼒ ② POST /login (id, pw) ③ PWハッシュ照合 → セッション保存 ④ ログイン成功 + Set-Cookie: session=abc123 ⑤ 以降のリクエスト + Cookie: session=abc123 🔎 セッション照合 (本⼈向けページ) ①〜④ がログインの 1 往復 — 以降は ⑤(Cookie ⾃動送信)を毎回繰り返す 200 OK

Slide 17

Slide 17 text

Cookie の重要な属性 属性 Secure 一言で HTTPS のときだ け送信 から読めなく HttpOnly JS する SameSite クロスサイトの 送信を制限 Domain 送信先ホストの 範囲 詳しく 盗聴・中間者攻撃 で ID が漏れない。常時 HTTPS でも必須( http:// を踏ませられると平文で飛ぶ) XSS での ID 窃取 を防ぐ。ただし XSS 自体は防げないので、XSS 対策は別途必須 CSRF を構造的に防ぐ。基本は Lax、他サイトからの リンク遷移(GET)のみ 送る。「サイト」の境界 は 登録可能ドメイン単位(サブドメインは同一サイト扱いで区別しない) 未指定が最も安全(発行ホストのみ = host-only)。 Domain=example.com を付けると サブドメイン全体 に送られ、範囲が広がる。共有が必要なときだけ付ける Set-Cookie: session=abc123; Secure; HttpOnly; SameSite=Lax 上 3 つは「付けない理由がなければ付ける」、Domain は逆に「必要がなければ付けない」。セッシ ョン Cookie ではこの形を デフォルト にする 7

Slide 18

Slide 18 text

セッションをめぐる代表的な攻撃 セッションハイジャック: ID を盗まれてなりすまされる → Secure / HttpOnly で対処 セッション固定攻撃: 攻撃者が用意した セッションID を被害者に使わせる → ログイン成功時に セッションID 再発行で対処 CSRF(Cross-Site Request Forgery): Cookie 自動送信を悪用、本人の意図しないリクエスト → SameSite + CSRF トークンで対処 8

Slide 19

Slide 19 text

便利さとCSRFのトレードオフ 👤 被害者 🪤 罠サイト 銀⾏にログイン中 🍪 bank の Cookie 保有 evil.example.com ① 罠サイトを訪問 ② 罠ページ(bank への送⾦ form ⼊り) ③ ブラウザが bank へリクエスト + 🍪 Cookie ⾃動付与 💥 サーバから⾒ると 正規のリクエスト — 意図しない送⾦が成⽴ 🛡 対策: SameSite 属性 + CSRF トークン 「Cookie が自動で付く」便利さは、そのまま CSRF の温床 でもある 9 🏦 正規サーバ bank.example.com

Slide 20

Slide 20 text

第 2 章小まとめ Web の通信は クライアント(ブラウザ)とサーバ の 1 往復、HTTP は本来ステートレス ログイン状態 = Cookie でセッション ID を毎回送り、サーバが照合する セッション ID はただのランダム文字列、本物の情報は サーバ側のストア にある Cookie の自動送信は便利だが CSRF の源。対処必須 10

Slide 21

Slide 21 text

第 3 章 [状態維持] トークン認証 / JWT セッション DB なしで状態維持できないか? という問いから、JWT という選択肢。 前半は 仕組み、後半は 運用と保存場所 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 22

Slide 22 text

状態をサーバ側に置くことの弱点 セッションという概念の欠陥ではなく、「本体を サーバ側ストア に置き、毎回照合する」設計から 来る制約。 そもそも セッション DB を用意・運用すること自体が手間(Redis を立てたくない) ブラウザ以外(モバイルや外部 API クライアント)は Cookie 前提が辛い マイクロサービス(複数の小さなサービスに分けた構成)間で毎回認証状況を問い合わせるのは 重い 2

Slide 23

Slide 23 text

発想の転換:状態を持たせ切ればストアは要らない 3 番号札(セッション ID)の代わりに、ユーザー情報を書いた「紙」そのものを渡してしまう。 💻 クライアント ① ログイン(ID / パスワード) ② 署名付きの紙(JWT)を渡す ⚙ サーバ 🗄 セッション DB 📄 ユーザー情報を書いた紙に サーバが 署名 = JWT 📄 クライアントが紙を保持 ③ 毎リクエスト、紙を提⽰ ④ 200 OK ✍ 署名を確認するだけ ❌ 照合しない 改ざんすれば署名が合わなくなる / ストアへの照合が消える = ステートレス この「署名付きの紙」の標準フォーマットが JWT (中身は誰でも読める。隠すのではなく 改ざんを検知 する仕組み)

Slide 24

Slide 24 text

署名検証なら発行と検証を分けられる:3 つの役割 4 ストアへの照合は発行したサーバにしかできない。 署名の検証は 公開鍵さえあれば別のサーバでもできる ので、役割を分けられる ④ 公開鍵取得 / キャッシュ 🔑 認証サービス トークンの発⾏役 ⓪ ログイン要求 ① トークン発⾏ 💻 クライアント トークンの持ち回り役 ② トークンを保持 ⼿元に置いて毎回使う ③ トークン提⽰ 🖥 リソースサーバ トークンの検証役 ⑤ 署名を検証 鍵があればできる = ストア照合不要

Slide 25

Slide 25 text

JWTの構造(3 パーツ) ヘッダ {"alg": "RS256", "typ": "JWT"} 5 ペイロード . 署名アルゴリズム {"sub": "123", "exp": 1800000000, "iss": "example.com"} 署名 . ユーザーID / 有効期限 / 発⾏元 RS256: 秘密鍵で署名 改ざんを検知する (中⾝は読める) 等は鍵ペア⽅式 (秘密鍵で署名・公開鍵で検証) ↓ 各パーツを Base64URL エンコードし「.」で連結 ※ RS256 xxxxx . yyyyy . zzzzz クライアントが持ち回る1つの⽂字列 ヘッダ: 署名アルゴリズム ペイロード: ユーザー ID / 有効期限 / 発行元 署名: ヘッダ + ペイロードに対する電子署名。

Slide 26

Slide 26 text

サーバはどうやって検証するか 1. 署名を検証 して改ざんを検知。方式は鍵の持ち方で 2 つ 共通鍵(HS256): 発行者と同じ鍵で再署名し、一致を確認 公開鍵ペア(RS256 等): 秘密鍵で作られた署名を 公開鍵で検証。検証側に秘密を配らずに 済み、複数アプリ構成の主流 2. ペイロードの exp (有効期限)を確認 3. 必要に応じて iss / aud を確認 セッションストアへの問い合わせが要らない = ステートレス認証 ※ IDaaS / OIDC では 鍵ペア方式(RS256 等)が事実上の標準。JWTの仕様上 共通鍵 (HS256 等) での署名も可能だが、本資料も以降は 鍵ペア方式前提 で説明する 6

Slide 27

Slide 27 text

JWT 検証は各アプリの責務 セッション方式は ストアを持つ 1 か所 だけが検証する。JWT は受け取った アプリそれぞれ が公 開鍵で自力検証する。検証の 責任ごと各所に分散 する。 検証コードは自作せず 実績あるライブラリ に任せる(→ 第 8 章) メリット:中央依存が消える 中央への 毎回の問い合わせが不要 → 低レイテンシ & SPOF 回避 各サービスが 独立して検証 → 複数台・マイクロサービスでスケール デメリット:責任が各所に散る 検証を 各アプリが正しく実装 する必要( exp / aud 漏れ = 自アプリの脆弱性) 公開鍵の配布・ローテーション を全アプリへ行き渡らせる運用 中央から 一斉に失効できない(→ 後半で詳説) 7

Slide 28

Slide 28 text

第 3 章(後半)[状態維持] トークンの運用と保存 仕組みの理解はここまで。後半は「どう運用し、どこに保存するか」 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 29

Slide 29 text

ステートレスの代償:トークンを途中で止められない ストアに聞かない = 発行済みの JWT は 期限が来るまで有効。盗まれても途中で止められない 🌐 クライアント ⚙ API サーバ AT ① API リクエスト + AT ② 200 OK(署名検証のみ) を検証するだけ 🔐 認証サーバ AT 発⾏・RT 管理 ⏱ AT 期限切れ ③ API リクエスト + 期限切れ AT ④ 401 Unauthorized ⑤ POST /refresh + RT(リフレッシュトークン) ⑥ 新しい AT(RT は認証サーバが管理・失効可能) AT: 短命・API サーバは署名検証のみ | RT: ⻑命だが認証サーバ側で失効できる 「API アクセスのたびに添える JWT」を アクセストークン(AT) と呼ぶ 盗まれたときの被害を限定するため、アクセストークンは数分〜1 時間程度の 短命 にする ただし短命にすると、今度は 数分ごとに再ログイン が必要になってしまう…(→ 次ページ) 9

Slide 30

Slide 30 text

短命の不便はリフレッシュトークンで解決する 「安全のための短命」と「利用し続けられる利便性」を、役割の違う 2 枚のトークン に分担させ る。 アクセストークン(AT) 役割 API アクセスのたびに添える 寿命 数分〜1 時間程度(短命) サーバ側の管理 なし(ステートレスに検証) 盗まれたら 期限切れまでの 短時間 で済む リフレッシュトークン(RT) アクセストークンの 再発行を頼む 専用 数日〜数十日(長命) 認証サーバ側で管理(いつでも失効できる) サーバ側で 失効させて止められる アクセストークンの期限が切れたら、裏でリフレッシュトークンを使って 自動で再発行 するので、 ユーザーは再ログイン不要。 長命でも安全側に倒せるのは「サーバが失効できる」から(第 2 章のセッションと同じ発想) 10

Slide 31

Slide 31 text

リフレッシュトークンのローテーション 1 長命な RT は盗まれたときの被害が大きい。だから「盗まれる前提」で、使うたびに使い捨てる。 🌐 クライアント 🔐 認証サーバ ① リフレッシュ要求(RT-1 を提⽰) 😈 攻撃者 を即無効化し、 新しい RT-2 を発⾏ RT-1 ② 新しい AT + RT-2 を返す 後⽇、RT-1 が盗まれていた場合… … ③ 無効化済みの RT-1 で要求 ④ 401 拒否(被害を遮断) ※ ローテーションは 仕様上の必須ではなくオプション(OAuth 2.0 のセキュリティ BCP が推奨 する強化策)。Cognito / Auth0 など IDaaS では 設定で有効化 できる

Slide 32

Slide 32 text

Web アプリの代表的な 3 構成 (サーバレンダリング) SSR 🌐 ブラウザ を表⽰するだけ 🍪 Cookie = 番号札だけ HTML 完成した HTML ⚙ サーバ 2 SPA + API 🌐 ブラウザ が画⾯を⽣成 🔑 トークンを JS が直接扱う JS ハイブリッド(Next.js) 🌐 ブラウザ 初回は HTML、以後 JS が更新 🍪 Cookie + 🔑 トークン (API) 初回 HTML → 以後 JSON ⚙ API サーバ ⚙ サーバ JSON を⽣成 + DB 🔑 セッション=認証情報の本体 トークンを検証するだけ ⽣成 + API 🔑 +セッション併⽤ 認証情報は サーバ側で完結 🔑 の置き場所の判断が必要(第 3 章) 両⽅の作法を使い分け HTML API + DB HTML 違いは「HTML をどこで組むか」と「JS がトークンを直接扱うか」の 2 点。 構成によって (認証情報)の置き場所が サーバ側からブラウザ側へ動く。これがこの後の保 存場所の議論につながる。

Slide 33

Slide 33 text

SPA + APIではクライアント JS がトークンを直接扱う 🌐 SPA ブラウザで動く JS 🔐 認証 API 📦 リソース API ① POST /login(ID・パスワード) ② JWT を返却 🔑 JS がトークンを保持 (どこに置く? → 次スライド) ③ GET /data + Authorization: Bearer JWT ④ データ応答 トークンは JS が明⽰的に付ける — Cookie のような⾃動送信ではない Cookie のように ブラウザが自動で付ける のではなく、クライアント JS が明示的に持ち回る これが次の「どこに保存するか問題」の前提 3

Slide 34

Slide 34 text

保存場所の定番論争:localStorage か Cookie か トークンの保存場所は SPA 開発で たびたび議論になる。 Cookieの方が安全だと言われるが、単純に Cookieに保存すれば安全という話ではない。 localStorage: JS から読める → XSS で盗まれる。ただし実装は単純で、別サイトの API にもそのまま使え る Cookie(HttpOnly + Secure + SameSite): JS から読めないので XSS でトークンを盗めない。代わりにCSRF 対策 と 「Set-Cookie を 返せる/Cookieを読めるサーバ」というインフラ構成要件が乗る つまりこれは保存場所の選択ではなく、インフラ構成(BFF の有無・オリジン)の選択に直結する 話 4

Slide 35

Slide 35 text

HttpOnly Cookieパターン(BFF / 同一オリジン) 🌐 ブラウザ(SPA) 🛡 BFF 📦 API 同⼀オリジンのサーバ ① POST /login(ID・パスワード) 🔑 JWT を発⾏し、 Cookie に載せて返す ② Set-Cookie: token=(HttpOnly) 🍪 Cookie の中⾝が JWT そのもの (HttpOnly なので JS からは読めない) ③ API 呼び出し(Cookie ⾃動付与 = JWT が⾶ぶ) ④ Cookie の JWT を Bearer に付け替え ⑤ データ ⑥ 応答 🍪 JS は触れないが、JWT はブラウザに保存され毎回往復する Set-Cookie で発行 → ブラウザが自動付与 → JS は token に触らない 5

Slide 36

Slide 36 text

発展:そもそもJWT をブラウザに出さないという選択肢 Cookie には セッション ID だけ を入れ、JWT は サーバ側(セッションストア)に保管。API へ は Authorization ヘッダに付け替え て呼ぶ。セッションとJWTを併用する形。 🛡 BFF 🌐 ブラウザ(SPA) 同⼀オリジンのサーバ 🗄 セッションストア 📦 API ① POST /login(ID・パスワード) ② 取得した JWT を保存(キー = セッション ID) ③ Set-Cookie: session=abc123(HttpOnly) 🍪 Cookie はセッション ID だけ (JWT はブラウザに渡らない) ④ API 呼び出し(Cookie ⾃動付与)⑤ セッション ID で JWT を取り出す ⑧ 応答 ⑥ Authorization: Bearer JWT ⑦ データ 🔑 JWT はセッションストアに留まる ― 第 2 章のセッション + 第 3 章のトークンの合流形 6

Slide 37

Slide 37 text

同一オリジン vs クロスオリジン 同一オリジン(推奨) フロント と API が 同じドメイン 例: https://app.example.com (フロント) + /api/... (同オリジン BFF) SameSite=Lax で素直に運用可、Cookie も host-only(発行ホスト限定)で最小範囲に 絞れる CSRF は SameSite + CSRF トークン で対 処 BFF を 1 枚立てるだけで構成は素直 7 クロスオリジン(要注意) 例: app.example.com + api.example.com 。同一サイト なので SameSite/CSRF 対策は 同一オリジンと同じ 増える考慮① Domain 指定: Domain=example.com が必須 → Cookie が 全 サブドメインに共有 され、露出範囲が広がる 増える考慮② CORS: Access-ControlAllow-Credentials: true + 具体オリジン指 定 + credentials: 'include' 。設定ミスは 脆弱性に直結 ※ 登録ドメインごと異なる 別サイト の Cookie 認証は成立しないと考える(選ばな い)

Slide 38

Slide 38 text

Cookieにトークンを保存するほうが安全ではあるが… 保存場所だけ localStorage → Cookie に張り替えても何も解決しない。 HttpOnly でない Cookie は XSS で同じように盗まれるし、HttpOnly にするには BFF / 同一オ リジン化という 構成変更 が必要になる。 推奨は HttpOnly Cookie + BFF。BFF を立てるコストは掛かるが、JS がトークンに触らない 形に倒せるため安全側 弱点もある: IDaaS等を利用して認証を委譲する場合、IDaaS の SPA 向け SDK は JS がトーク ンを扱う前提 が多く、BFF パターンの お手軽な実装は少なめ。Auth.js(Next.js)や Duende BFF(.NET)のような サーバ側ライブラリを持つスタックも一部ある ので、自分の環境で何が 使えるか 採用前によく確認(→ 第 8 章) 構成変更が現実的でない純 SPA + API では、ブラウザ保存(メモリ / localStorage)が標準的 (Amplify 等 SPA SDK の既定)。JS から触れる場所に置く以上、XSS 対策とトークン短命化 が前提 になる 結論は保存場所単体では出ない。構成(BFF の有無等)の全体設計 で判断する 8

Slide 39

Slide 39 text

補足:Next.jsは「BFF 付き SPA」になれるハイブリッド Next.js は SPA(React) の画面と サーバ処理(SSR / Route Handler / Server Actions) を 1 つのアプリに同居 させたハイブリッド構成。BFF を別途立てなくても、最初から同一オリジ ンのサーバが付いてくる。 認証処理(IDaaS とのやり取り・トークン管理)は サーバ側で実行 し、ブラウザには HttpOnly Cookie のセッションだけ を渡せる(Auth.js がまさにこの形) トークンの持ち方は 2 通りから選べる: ストアに置く セッション方式(DB) → サーバー管理なので即失効可能 暗号化して Cookie 自体に持たせる方式(Auth.js の既定)。 → ストア不要 フロントと API が同一オリジンなので、クロスオリジン特有の CORS / SameSite の考慮も出 ない 「BFF を立てるコスト」がフレームワーク選定でほぼ消える。構成の悩みをスタック選びで先に 解く 例 9

Slide 40

Slide 40 text

アンチパターン:セッション ID の代わりに JWTを使う 「JWT のほうがモダン」という理由で、Cookie に入れるセッション ID を JWT に置き換えるの は 典型的なアンチパターン。 ストアを残すなら: 毎回ストアに照合する時点で JWT の利点(ステートレス検証)は 使われていない。ただの 「長くて複雑なセッション ID」になるだけ ストアを無くすなら: ログアウトしても 発行済みの JWT は期限まで有効なまま。サーバ側に「消す場所」がそもそ もない 真面目に対処すると 短命化 + リフレッシュトークン管理 や ブロックリスト が必要 = 結局サ ーバ側に状態(ストア)が戻ってくる。単一アプリでは複雑さだけが増える 第 2 章の通り、セッション ID は 意味のないランダム文字列 であることが価値。中身にデータを 持たせる必要がそもそもない JWT は 複数サーバ / サービスに検証を分散したいとき の道具。単一アプリのログイン状態維持な ら ランダムなセッション ID で十分 10

Slide 41

Slide 41 text

ログアウトの設計 「ログイン状態をどう消すか」は方式で難易度が変わる。JWT の失効しにくさがここに直結する。 セッション方式: サーバ側のセッションを 破棄 すれば即座に無効化できる(簡単) JWT をユーザーに持たせる方式(SPA等): アクセストークンは自己完結ゆえ サーバから即時失効できない 短命化 + リフレッシュトークンをサーバ側で失効 させ、再発行を止めるのが現実解 即時失効できない・リフレッシュトークンをブラウザに置くリスクから、対ブラウザでは「ト ークンを JS に持たせず、サーバ側セッション + HttpOnly Cookie に寄せる」推奨が強まっ ている SSO 連携時(第 7 章): 自アプリだけ切っても IdP で再ログインされる → IdP 側のログアウト やシングルログアウトも考慮 1

Slide 42

Slide 42 text

第 3 章小まとめ JWT は「サーバが署名した、中身が 読める 紙」という フォーマット(暗号化ではない) セッション DB を持つか、JWT に状態を持たせ切るかは 設計の選択。組み合わせる構成も普通 にある SPA + API ではクライアント JS が自分でトークンを持ち回る(Cookie 方式との大きな違い) ステートレスで複数台に強いが、失効が難しいので 短命 + リフレッシュ で運用 単一アプリのセッション維持に JWT は不要。セッション ID の代わりに JWT を使わない 保存場所は 構成で決まる。BFF があれば HttpOnly Cookie、純 SPA は ブラウザ保存 + XSS 対策・短命化 が標準形 2

Slide 43

Slide 43 text

第 4 章 [手段] 認証の 3 要素 ここから「ログイン手段」の話。まず手段を整理する 3 つの軸から 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 44

Slide 44 text

認証の3 要素 4 知識 所有 生体 弱点 漏れる 推測される 弱点 盗まれる 紛失する 弱点 偽装される 取り替えられない Something you know パスワード PIN 秘密の質問 Something you have スマートフォン ハードウェアキー SIM(電話番号) Something you are 指紋 顔 虹彩

Slide 45

Slide 45 text

1 要素の限界とMFA:なぜ「異なる要素」を重ねるのか 1 要素は、その要素の 弱点を突かれたら終わり(パスワードなら「漏れたら終わり」)。 異なる要素 を重ねると、攻撃者は 種類の違う攻撃を同時に 成立させる必要がある。 ✅ 異なる要素を重ねる = MFA 🔑 パスワード + 📱 TOTP / スマホ (知識) (所有) ❌ 同じ要素を重ねる 🔑 パスワード + ❓ 秘密の質問 (知識) (知識) 破るために必要な攻撃 ↓ 破るために必要な攻撃 ↓ ネット越しの漏えい・リスト攻撃 かつ スマホを物理的に盗む 漏えい・推測・SNS で調べる 同じ攻撃 で両⽅破れる 種類の違う攻撃を 2 つ同時に → 困難 実質 1 要素 — MFA とは呼ばない 5

Slide 46

Slide 46 text

第 5 章 [手段] パスワード 最も古典的な認証手段。 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 47

Slide 47 text

パスワードは「保存しない」 サーバはパスワードを 平文で保存してはいけない 万一漏れたら、他サービスの使い回し被害まで広がる サーバは「照合できればよい」、元のパスワードを保存する必要はない 7

Slide 48

Slide 48 text

ハッシュとは 8 ❌ NG: 平⽂で保存 🔑 password123 🗄 DB password123 のまま 💥 DB漏えい 全ユーザーのパスワード が丸⾒え → 他サービスへの 使い回し被害も ✅ OK: ハッシュ化して保存 🔑 password123 🔒 bcrypt / Argon2 🗄 DB $2b$12$Xy3... 💥 DB漏えい 🔒 ハッシュからは 元に戻せない → 直接の被害を ⼤きく抑えられる 同じ入力から同じ結果が出るが、結果から元には戻せない 一方向の変換

Slide 49

Slide 49 text

ソルトを足す 9 同じパスワード + salt 🧂 → ハッシュ化 異なるハッシュ ユーザーA 🔑 password123 + 🧂 8f3a... $2b$.. ユーザーB 🔑 password123 + 🧂 b1c9... $2b$.. ユーザーC 🔑 password123 + 🧂 e7d2... $2b$.. 同じ password でもユーザーごとに 違うハッシュ → 事前計算表 (レインボーテーブル) 攻撃が無効化 ソルトは平⽂のまま DB に保存してよい(秘密ではない) ユーザーごとに ランダム文字列(ソルト)を付けてからハッシュ化 レインボーテーブル攻撃が無効になる ソルトはユーザーと一緒にサーバに保存

Slide 50

Slide 50 text

ストレッチング 単純ハッシュでは高速で総当たりされ破られる ハッシュを意図的に遅くするアルゴリズムを使う 代表: bcrypt / Argon2(ソルト + ストレッチングを一括でやってくれる) 10

Slide 51

Slide 51 text

使い回しというユーザー側のリスク サーバを完璧にしても、ユーザーが他サービスと同じパスワードを使えば被害は来る(パスワー ドリスト攻撃) アプリ側でできる対策 MFA の導入 漏えいパスワード辞書とのつき合わせ 1

Slide 52

Slide 52 text

第 5 章小まとめ 平文保存は厳禁。ハッシュ + ソルト + ストレッチング が最低ライン アルゴリズムは Argon2id が第一候補(bcrypt / PBKDF2も候補)。SHA-256 など高速ハッシ ュ単体は不適 パスワード使い回しというユーザー側のリスクは MFA で補う 2

Slide 53

Slide 53 text

第 6 章 [手段] 多要素認証(MFA)& パスキー 第 4 章の 3 要素 + パスキーを現実の運用に落とす 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 54

Slide 54 text

代表的なMFA の手段 4 第 4 章の通り、MFA = 異なる要素を 2 つ以上。1 つ目はパスワード(知識)が多いので、2 つ目 は実務ではほぼ 「所有」 になる。 手段 TOTP(認証アプリ) SMS プッシュ通知承認 パスキー / ハードウェアキー 要素 特徴 所有 30 秒ごとの 6 桁コード。低コストで導入できる 定番(→ 次ページ) 所有 導入は容易だが、推奨されなくなってきた(→ 後述) 所有 承認連打を狙う疲労攻撃 に注意。番号照合等を組み合わせる。 所有 + 生体/知識(PIN) フィッシング耐性が最強。単体で 2 要素を内包(→ 後述) ※補足:メールは MFA ではない ログイン URL や 6 桁コードをメールで送る方式。パスワード以外の認証要素として、現実に広 く使われている。 正体は「受信箱にアクセスできること」の確認。特定デバイスの所有を証明しないため、厳密に は 「所有」要素といえない 安全性は ユーザーのメールアカウントの強度と等価。受信箱が破られたら終わり(→ 後述の「リ セット経路」と同じ構造)

Slide 55

Slide 55 text

TOTPの仕組み 5 📱 認証アプリ (Google Authenticator 🔐 共有秘密鍵 ⚙ サーバ 等) 🔐 同じ共有秘密鍵 を保持 JBSWY3DPEHPK3PXP JBSWY3DPEHPK3PXP ⏱ 現在時刻 (30秒単位) ⏱ サーバの現在時刻 🔢 HMAC (秘密鍵, 時刻) 🔢 同じ HMAC 計算 6 桁コード ユーザーが6桁コードを⼊⼒して送信 サーバが同じ計算で照合 ⼀致 → 認証OK 期待する6桁コード 両者が同じ秘密鍵と時刻から 独⽴に 同じコードを計算。共有秘密鍵は登録後ネットワークを流れない (SMS のようなコード配送も不要) Google Authenticator / 1Password などで生成される 6 桁。低コストで導入できる MFA の 定 番

Slide 56

Slide 56 text

SMS による MFA のリスク SIM スワップ攻撃(キャリアに偽の本人確認で番号を乗っ取る) NIST ガイドラインでも 非推奨寄り の扱い 新規導入なら TOTP やアプリ通知を優先 6

Slide 57

Slide 57 text

パスキー(WebAuthn)登録〜認証の仕組み ① 登録 Register 📱 デバイス (ブラウザ/OS) ⚙ サーバ ユーザーが登録を開始 チャレンジ + ユーザー情報 👆 ⽣体認証 → 鍵ペア⽣成 秘密鍵はデバイス内に保管 🔑 公開鍵 を送信 🔑 公開鍵をユーザーに 紐づけて保存 ② 認証 Authenticate 📱 デバイス (ブラウザ/OS) 7 ⚙ サーバ チャレンジ (ランダム⽂字列) 👆 ⽣体認証 → 秘密鍵で署名 🖊 チャレンジへの署名を送信 ✅ 公開鍵で署名を検証 → 認証OK 秘密鍵はサーバに送られない / パスキーはサイト (オリジン) に紐づき、偽サイトでは認証できない デバイスに保存した 秘密鍵 で本人確認 ユーザーは 指紋 / 顔 / PIN でデバイスを解錠 するだけ 秘密鍵は サーバに送られない(同期パスキーはクラウド経由で端末間同期)/ フィッシングに構 造的に強い 新規プロジェクトでは視野に入れたい現代的な選択肢

Slide 58

Slide 58 text

推奨パターン 普通の Web アプリ: パスワード + TOTP を基本 より強い保護が必要: パスキー(単体で多要素を内包しパスワードの代替になる。フィッシングに 強く UX も良い) SMS は最後の手段。メインの MFA としては 避ける 8

Slide 59

Slide 59 text

落とし穴:パスワードリセットが認証の「裏口」になる 正面(パスワード + MFA / パスキー)をどれだけ固めても、認証の強度は一番弱い経路で決まる。 「パスワードを忘れた方」の経路が弱ければ、攻撃者は MFA と戦わず そこを通る。 メールでリセット URL を送る定番方式は、実質 「メール受信箱」だけの認証。受信箱を破られ ると MFA ごと迂回 される リセット URL は 短時間で失効するワンタイムトークン に(URL の漏えい = 乗っ取りと等価) リセット時にも MFA を要求 し、完了したら 全セッションを失効 + 本人に通知 「秘密の質問」での回復は知識 1 要素への 格下げ。使わない 現実的にはメールや SMS による回復が主流。ただし採用するなら 上記の緩和策(短命トークン・ リセット時 MFA・通知)が前提。アカウントの実質強度は 受信箱や SIM の強度まで下がる。 ただし、より高い保証が必要な領域では、事前保存のリカバリーコード、複数 MFA、本人確認、待 機期間、手動レビューなどを組み合わせて強度を高める。 9

Slide 60

Slide 60 text

第 6 章小まとめ パスワード単体は脆弱。MFA で要素を増やす のが基本対策 TOTP / SMS / プッシュ は 強度と運用コストにトレードオフ パスキーは フィッシング耐性 が強み、所有 + 生体(または PIN)を単体で内包 ログイン時の MFA は 基本。ただし 操作のたびに要求するのは過剰。送金や設定変更など 重要 操作での再認証(step-up) が落としどころ リセット(回復)経路は 裏口。ここが弱いと MFA も無意味、可能であれば 正面と同じ強度 で 守る 10

Slide 61

Slide 61 text

第 7 章 [委譲] ソーシャルログイン & SSO ソーシャルアカウントでログイン。SSO の一種として捉える 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 62

Slide 62 text

委譲とは何か 「自アプリでパスワード等の 手段を直接扱わない」設計。手段の運用を IdP(Identity Provider) に外出しし、自アプリは 結果(ID トークン等)だけ受け取る。 自アプリ:パスワードを保存しない/MFA 実装も持たない IdP:手段の保管・検証・MFA・ログ・失効までを一括で持つ やり取り:トークンや署名済みアサーションで「誰がいつ認証されたか」を伝える → ログインの 手段を IdP に置き換えるだけで、その後の状態維持(セッション ID/JWT 保持) は 依然として自アプリの責任 2

Slide 63

Slide 63 text

IdP と 自アプリの責任分担 フェーズ 1:ログインの瞬間(1 回だけ) 経路 A:⾃アプリで認証する ユーザー 3 経路 B:認証を IdP に委ねる 【委譲】 【⼿段】 IdP 【⼿段】 パスワード/パスキー等を検証 IdP 側で検証 (Google / Cognito 等) 認証ロジックを⾃分で持つ 認証成功 ⾃アプリは結果(ID Token 等)を受け取るだけ ⾃アプリがセッション ID/トークンを発⾏ Set-Cookie / レスポンスボディ等で渡す フェーズ 2:ログイン後(毎リクエスト) 【状態維持】 毎回 Cookie / Authorization ヘッダで セッション ID/トークンを送る ブラウザ ⾃アプリ 検証 OK ならレスポンスを返す(再認証は不要) この帯の中で「⼿段」は登場しない。 トークン⽅式のみ:期限切れになったら refresh_token で新しいトークンを取得 発⾏済みの ID/トークンを使い回すだけ。 (再認証は不要 / 第 4 章で詳述) 経路 B(オレンジ)が委譲。手段は IdP 側で動き、状態維持は自アプリ側で持つという分業になる

Slide 64

Slide 64 text

ソーシャルログイン(OIDC)の位置づけ 👤 ユーザー OpenID Connect (OIDC) ①「Google でログイン」を押す 🏢 ⾃アプリ パスワードを保存しない ④ ログイン完了 4 ② IdP の画⾯でパスワード⼊⼒ ③ ID トークン(署名付き) 「あなたは Alice」という証明 以降は⾃アプリのセッション(状態維持は⾃アプリの責任) 🔑 IdP(Google など) パスワードはここにだけ渡る ⚠ IdP 障害時はログイン不可(外部依存) 「Google でログイン」などの仕組み、多くは OpenID Connect パスワードは IdP にだけ渡る ので、自アプリは持たなくて済む / 代わりに外部 IdP に依存する

Slide 65

Slide 65 text

OIDC で登場する3 つのトークン:AT / RT との関係 第 3 章のアクセストークン(AT)/ リフレッシュトークン(RT)に、OIDC では ID トークン が 加わる。 3 つとも、ログイン成功時に IdP からまとめて発行 されて渡される トークン 役割 第 3 章との関係 「誰が・いつ・どの IdP で 認証されたか」 ID トークン を伝える 新登場。中身は JWT ログインの証明書 第 3 章と同じ。ただし外部 IdP 発行分は IdP の API 用(自アプリ アクセストークン API を呼ぶための 鍵 API 用ではない) リフレッシュトー アクセストークンの 再発行 第 3 章と同じ。長命・サーバ側で厳重管理 クン ID トークンは自アプリが 検証して受け取ったら役目を終える。その後のログイン状態は 自アプリ のセッション / トークン に引き継ぐ(状態維持は自アプリの責任) 5

Slide 66

Slide 66 text

ID トークンとアクセストークンを混同しない 6 OIDC では性質の違う 2 種類のトークンが登場する。用途のクロス利用はアンチパターン 🔐 IdP(認証サーバ) 発⾏ 🪪 ID トークン 「誰がログインしたか」を伝える ✓ 本⼈確認に使う ❌ 認可に流⽤しない 🖥 ⾃アプリ 検証して本⼈確認に使う 発⾏ 🎫 アクセストークン 「何にアクセスしてよいか」の許可証 ❌ 本⼈確認に使わない ✓ API の認可に使う ⚙ API(リソースサーバ) リクエストに添えて送る ID トークンで API を呼ぶ: 宛先(aud)が API 宛てでないため、APIが受け入れるにはaud検証 を緩めるしかなく、緩めると 同じ IdP を使う他アプリ向けのトークンと区別できなくなる アクセストークンでログイン判定: 「誰に発行されたか」の保証がないため、他アプリに渡ったト ークンでなりすまし が成立する

Slide 67

Slide 67 text

補足:OAuth 2.0とOIDCは別物 OIDC は、OAuth 2.0 の仕組み(認可コードフロー等)を流用して その上に「認証」を載せた拡張 仕様。 流れは同じでも目的が違う。OAuth 2.0 自体は「認可(権限の委譲)」の仕組み で、本人確認の機 能は持たない。 主な目的 発行されるもの OAuth 2.0 認可(権限の委譲) アクセストークン OIDC 認証(本人確認) ID トークン(+アクセストークン) 「誰がログインしたか」を知りたいログインでは OIDC を使う。OAuth 2.0 だけで本人確認を組む のはアンチパターン。 7

Slide 68

Slide 68 text

SSO(シングルサインオン)とは 8 IdP に 1 回ログインすれば、連携する複数のサービスすべてに入れる 仕組み。条件は、各サービ スが認証を 同じ IdP に委譲 していること。 ❌ SSO なし — サービスごとにログイン 🔑 ログイン 🙂 ユーザー 🔑 ログイン 🔑 ログイン 3 ✅ SSO あり — ⽞関は IdP 1 つ 📦 サービス A 📦 サービス B 📦 サービス C サービス = パスワード⼊⼒ 3 回 📦 サービス A 🙂 ユーザー 🔐 IdP セッション保持 🔑 ログインは 1 回だけ 📦 サービス B 📦 サービス C 認証済み ✓ 画⾯なしで素通り 何サービス増えても⼊⼒は 1 回 種明かしは第 2 章と同じで、IdP 自身がセッションを持っている。 ソーシャルログインも Google をIdPとした SSO の一種 と考えられる

Slide 69

Slide 69 text

SSO の2 大プロトコル:OIDC と SAML OIDC(OpenID Connect) SAML 用途 コンシューマ向け エンタープライズ向け ベース OAuth 2.0 + 認証レイヤー XML ベースの標準プロトコル 代表例 Google ログイン、GitHub ログイン 社内ポータル、オンプレ IdP どちらも「外部 IdP に認証を委譲する」パターンは同じ。自前でパスワードを持たなくて済む一 方、IdP 障害の影響を受ける。 9

Slide 70

Slide 70 text

委譲は連鎖できる:委譲の委譲(フェデレーション) 委譲の連鎖(フェデレーション) 💻 ⾃アプリ つなぐ相⼿は 1 つだけ 委譲 ① 1 さらに先の委譲先 委譲 ②(フェデレーション) 🔑 Cognito(IDaaS) 委譲先であり、委譲元でもある Google GitHub 社内 SAML IdP ✅ ⾃アプリから⾒える IdP は常に 1 つ ログイン⼿段が増えてもコードは変わらない 💡 IdP の追加は IDaaS の設定だけ ホップが増える分、障害点も増える点は注意 委譲先の IdP が さらに別の IdP へ委譲 できる。この形が第 8 章の IDaaS + ソーシャル連携 の 正体

Slide 71

Slide 71 text

第 7 章小まとめ 委譲 = 手段を IdP に外出し、自アプリは結果(ID トークン等)だけ受け取る OIDC は OAuth 2.0 + 認証、SAML は エンタープライズ向け 委譲は 連鎖できる(自アプリ → IDaaS → Google)。アプリの接続先は IdP 1 本に集約できる パスワードを自前で持たなくて済む反面、IdP 障害が直撃する 依存リスクがある ログイン処理を委譲しても 「セッション/トークンの状態維持は自アプリの責任」 は変わらない 2

Slide 72

Slide 72 text

第 8 章 実装の選択肢 方針は IDaaS が基本路線。ただし「IDaaS を選んで終わり」ではない。アプリ側に残る つ なぎ役 まで含めて持ち帰る 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 73

Slide 73 text

結論:認証は自作しない 認証ロジックはどのアプリでも同じで、共通パターンが確立している。作るものではなく、選ぶも の。 パスワード保存 → Argon2 でハッシュ化 セッション ID → ランダム生成 してストアに保存 JWT 検証 → 署名を鍵で確認 車輪の再発明は不要。ロジックは 実戦済みのライブラリ、認証サービス本体は IDaaS に任せる 4

Slide 74

Slide 74 text

なぜIDaaSか 5 🛠 ⾃作 (DIY) 📚 認証ライブラリ + ⾃前のロジック 🗄 DB スキーマ設計・運⽤ 🔐 PWハッシュ / セッション / トークン管理 🛡 MFA / パスキー / SSO の⾃前実装 🔧 脆弱性対応・漏えい対応 ❌ 全部 ⾃分の責任 ❌ 正しく作り「続ける」 コストが⾼い ☁ マネージドサービス 🔌 SDK で数⾏ → 認証完了 ✅ ユーザー管理はサービス任せ ✅ PWハッシュ / トークン発⾏ は実装済み ✅ MFA / パスキー / SSO 設定で 有効化 ✅ 脆弱性対応はサービス側 例: Cognito / Auth0 / funnaly auth ✅ 99% のケースで こちらが基本路線 認証は「正しく作り 続ける コスト」が高い領域(パスワード運用・MFA・漏えい対応…第 5〜6 章の全部)。IDaaS が基本路線

Slide 75

Slide 75 text

ただし「IDaaS を選んで終わり」ではない 🏠 ⾃アプリ アプリ本体(画⾯・API) 🌐 ブラウザ Cookie / トークンを持つ 毎リクエスト IDaaS 🔌 つなぎ役ライブラリ ① IDaaS 連携(リダイレクト・ ログイン時・検証 コールバック・トークン取得) ② 状態維持 (セッション / Cookie 管理) ③ ルート保護(未ログインを弾く) 6 🔐 IDaaS(認証サービス) / Cognito Auth0 fannaly auth 担当 =「⼿段」の運⽤ ・ユーザー DB ・パスワード / MFA ・トークン発⾏ に外出しできるのは「⼿段」 ― 状態維持はつなぎ役 = ⾃アプリ側の仕事のまま 第 3 章の 3 役でいえば 認証サービスを IDaaS に置いた形。手段は外出しできても、つなぎ役 (コールバック処理・状態維持・ルート保護)は自アプリ側に残る

Slide 76

Slide 76 text

つなぎ役ライブラリの守備範囲を確認する つなぎ役はライブラリを使う。主な仕事は 3 つ。 どこまでやってくれるかはライブラリ次第。採用前にこの 3 点で確認する。 つなぎ役 の仕事 ① IDaaS 連携 ② 状態維 持 ③ ルート 保護 具体的には リダイレクト・コールバック(state / PKCE 検証)・トークン取得・ログアウト連 携 セッション / Cookie 管理(第 2・3 章) 未ログインを弾く フルスタック系 (Auth.js / Devise 等) SPA 向け SDK(amplify.js / auth0-spa-js 等) ✓(Devise は ✓ OmniAuth 併用) ✓ HttpOnly Cookie △ クライアント側保存(localStorage / メモリ) 込み で自動更新。HttpOnly Cookie は不可 ✓ ミドルウェアで提供 △ 部品はあるが組み込みは自分 一番差が出るのは ②。SPA SDK にも ② は付くが JS から触れる保存場所 になる。第 3 章の保存 場所問題が そのまま残る。 ① のうち ログアウト連携(IdP 側のセッションも切るか) も差が大きい。確認を忘れると「アプ リからログアウトしたのに再ログインなしで入れる」が起きる 7

Slide 77

Slide 77 text

補足: Cognito をSSRで使うと Next.js なら: 公式の Next.js アダプタ(@aws-amplify/adapter-nextjs)が ② 状態維持まで公 式対応(2025/3 から HttpOnly Cookie も可)。③ は公式の middleware パターンを 自分で 組み込む Python / Ruby / Go など他のスタックなら: 公式 SDK は ① 止まり。スタック定番のサード パーティライブラリ(django-allauth / Authlib / OmniAuth / Auth.js の Cognito プロバイダ 等)でつなぐ方が ②③ まで揃う 教訓: 守備範囲は スタックと SDK のバージョンで変わる。「公式だから」ではなく、採用時点の 守備範囲で選ぶ 8

Slide 78

Slide 78 text

ライブラリは構成で決まる Next.js / TypeScript → Auth.js(旧 NextAuth) Express / Node.js → Passport.js Django / Python → django-allauth FastAPI / Python → Authlib / FastAPI-Users Ruby on Rails / Ruby → Devise(+ OmniAuth でソーシャル拡張) OIDC 準拠の IDaaS(fannaly auth 等)→ 専用の「公式ライブラリ」は 無いのが普通。汎用の OIDC クライアント(openid-client / Authlib 等)や、上記ライブラリの OIDC プロバイダ設 定 でつなぐ Webフレームワークを選んだ時点でほぼ決まる。決まったらライブラリの 守備範囲(①〜③のどこ までか)の確認を忘れずに 9

Slide 79

Slide 79 text

IDaaS の選び方 AWS Cognito 10 Auth0 fannaly auth シンプルな認証なら SSO・多機能なら (※これは宣伝です) AWS とつなぎやすい エンタープライズ SSO / 多 大規模 B2C・会員統合なら User Pool でユーザー管理 IdP 連携 Prismatix社(クラスメソッ 細かなカスタマイズに強い ドグループ)製OIDC 準拠の 低コスト 公式ライブラリの対応言語が 会員 ID 統合基盤 多い 複数チャネルの顧客認証を統 合 会員・ポイント管理と連携

Slide 80

Slide 80 text

第 8 章小まとめ 認証サービス本体は IDaaS が基本路線 ただし IDaaS だけでは動かない。つなぎ役ライブラリ が必須で、それは スタックで決まる ライブラリの 守備範囲には差がある。状態維持(セッション管理)まで含むか 採用前に確認 IDaaS は シンプル → Cognito / SSO・多機能 → Auth0 / 大規模 B2C・会員統合 → fannaly auth(組み合わせの実例は付録の対応表) 1

Slide 81

Slide 81 text

第 9 章 まとめ 全体マップに戻り、次の学びを示す 認証とは ▸ 状態維持 ▸ ⼿段 ▸ 委譲 ▸ 実装

Slide 82

Slide 82 text

認証を3 観点で振り返る 「認証」を 1 語で混ぜず、メタ概念(認証とは何か)+ 実装の 3 観点(状態維持 / 手段 / 委譲) に切り分けた。 観点 問い 答えの軸(章) 状態維持 ログイン状態を毎リクエストどう保つか Cookie + セッション か JWT(第 2・3 章) 手段 どうやって本人だと確かめるか パスワード + MFA、可能ならパスキー(第 4〜6 章) 委譲 手段を自前で持つか、外に出すか IdP に外出し(OIDC / SAML)(第 7 章) 手段 はログイン時の 1 回/状態維持 はその後の毎リクエスト/委譲 は手段の置き場所を外へ。土 台(状態維持)から固める順で進めた 3

Slide 83

Slide 83 text

持ち帰る判断基準:構成が決まれば状態維持も決まる 3 観点のうち 状態維持 は、最初に選んだ 構成 でほぼ自動的に決まる。「前提が変わると正解も変 わる」の一番わかりやすい例。 あなたの構成 SSR(同一オリジン) SPA + BFF(同一オリジン API) SPA + 外部 / 別サイト API モバイル / 外部 API 状態維持のデフォルト Cookie + セッション HttpOnly Cookie(+ 短命 JWT) ブラウザ保存(SDK 既定)+ 短命化・refresh 厳格管理 トークン(短命 + リフレッシュ + ローテーション) 外さないポイント 3 属性 + CSRF トークン JS はトークンに触らない XSS 対策必須/正攻法は BFF 化 Cookie 前提が成り立たない領域 手段 はパスワード + TOTP を基本に、可能なら パスキー。委譲 で自前運用を避けるなら IdP(第 7 章) 4

Slide 84

Slide 84 text

付録:ライブラリ × IDaaS対応表 ライブラリ Auth.js (Next.js) Passport.js (Node) django-allauth (Django) Devise (Rails) Cognito ✓ ビルトイン △ 汎用 OIDC strategy ✓ ビルトイン ✓ omniauth-cognito-idp Auth0 ✓ ビルトイン ✓ passport-auth0 ✓ ビルトイン ✓ omniauth-auth0 5 OIDC(fannaly auth) ✓ ✓ ✓ ✓ ✓ = 公式 / 準公式プラグインあり、設定数行で動く △ = OIDC エンドポイントを手動設定すれば動く(IDaaS を使わずライブラリ単体でのローカル 認証も可) ※ Firebase Auth はこの表に載らない: 標準の OIDC IdP としてリダイレクトで繋ぐ製品では なく、クライアント SDK でログインしサーバは ID トークンを検証する別モデル(つなぎ役ライ ブラリを使わず Firebase のレールに乗る)

Slide 85

Slide 85 text

付録:略語集 通信・構成 HTTP: Web の通信プロトコ ル SSR: サーバ側で HTML を生 成 SPA: Single Page Application BFF: フロント専用バックエ ンド CORS: クロスオリジン通信 の許可制御 6 攻撃・対策 XSS: Cross-Site Scripting CSRF: Cross-Site Request Forgery MFA: 多要素認証 TOTP: 時刻ベースのワンタイ ムパスワード SPOF: 単一障害点 委譲・実装 JWT: JSON Web Token OIDC: OpenID Connect (認証) SAML: XML ベースの SSO 規格 SSO: シングルサインオン IdP: Identity Provider(ID 提供者) IDaaS: 認証のマネージドサ ービス

Slide 86

Slide 86 text

ご清聴ありがとうございました