本記事について
当サイトを閲覧いただきありがとうございます。 本記事はシリーズ『生成AI時代のアーキテクチャ超入門』の「ソフトウェアアーキテクチャ」カテゴリ最終記事(第7弾)として、サーバ側の認証・セッションについて解説する記事です。
本記事の問いは「ログイン後のセッションをどう持つか」です。サーバセッション vs JWT・OAuth 2.0/OIDC・Cookie属性の安全設定まで扱い、認証強度(MFA / Passkey / IDaaS)とブラウザ防御(XSS / CSP)はそれぞれセキュリティ章・フロントエンド章に委ねます。
本記事のテーマについてさらに詳しく知りたい方は『セキュア・バイ・デザイン』も参考にしてみてください。
この記事の結論
- 同一ドメインはCookieセッション、ドメイン横断はJWT
- JWTは短命(15分)+Refresh Token Rotation。localStorageには置かない
- OAuthはAuthorization Code+PKCE一択、外部連携はOIDC
- Cookie属性(HttpOnly / Secure / SameSite)は必ず明示する
この記事を読む前に
本記事はプログラムやAPIといった開発寄りの話が中心です。IT用語にあまり馴染みがない方は、基礎編の「プログラムとAPIの基本」を先に読んでおくと格段に分かりやすくなると思います。また、読んでいて分からない用語が出てきたときは用語集で調べながら読み進められます。
そもそも認証・セッション設計とは何か
認証・セッション設計とは、ざっくり言えば「ログイン後のユーザーをどうやって覚えておくかの仕組みを決めること」です。
遊園地の入場を想像してください。入口でチケットを見せて本人確認する(認証)のは一度きりで、園内ではリストバンド(セッション)を見せるだけでアトラクションに乗れます。リストバンドをサーバー側で管理するか、来場者自身に持たせるか──この選択がサーバセッション方式とJWT方式の違いです。
なお混同されがちですが、認証(Authentication)は「あなたは誰ですか」を確認する処理、認可(Authorization)は「あなたは何ができますか」を決める処理です。「ログインできたから管理者操作もできる」は典型的な混同で、この2つは別物として設計します。
なぜ認証・セッション設計が重要なのか
もしセッション管理の選択を誤ると、致命的なセキュリティホールになります。JWTの保管場所を間違えればXSSで盗まれ、Cookieの属性設定を忘れればCSRFで操作される──セッション周りの設計ミスは直接的な不正アクセスにつながります。
さらにマイクロサービス化すると、モノリスでは1箇所で済んだセッション管理が全サービスにまたがります。最初に方式を統一しないと、サービスごとにバラバラな認証実装が乱立します。AIエージェントがAPIを叩く時代では、人間のブラウザセッションとは別の認証フローも必要になり、両方を見据えた設計が求められます。
セッション管理の2大方式
認証後、再ログインなしでAPIを使い続けられるようにする仕組みがセッション管理です。方式は大きく2つに分かれます。
サーバセッション ― 同一ドメインの既定解
ログイン成功時にサーバーがランダムなセッションIDを発行してCookieに保存させ、以降のリクエストではRedis等のストアを参照してユーザー情報を取り出す方式です。即時失効が可能(ストアから消せば無効)、漏洩時の被害を局所化しやすい、ライブラリが成熟しているという強みがあり、同一ドメインの一般的なWebアプリ・SPAならサーバセッションで十分かつ安全です。弱点はセッションストアの運用が必要なことと、スケールアウト時に全台でストアを共有する必要があることです。
JWT ― ドメイン横断のための道具
JWTは、ユーザー情報そのものを署名付きトークン(Header.Payload.Signature)に詰めてクライアントに渡す方式です。サーバーは署名を検証するだけで認証でき、状態を持たない(ステートレス)ため、マイクロサービスが複数立ち並ぶ構成で各サービスが独立して認証処理できます。
代わりに罠も多い方式です。即時失効が困難(トークンは期限まで有効)なため、短命のAccess Token+httpOnly Cookieに入れたRefresh Tokenの組み合わせが定石です。ペイロードはBase64で誰でもデコードできるので機密情報を入れてはならず、localStorageに保存するとXSS一発で盗まれるためhttpOnly Cookieに保管します。「JWT=localStorage」という組み合わせは、2024年以降のセキュリティガイドラインでは事実上の禁則です。
OAuth 2.0 / OIDC
OAuth 2.0は「認可の委譲」のプロトコルで、「このアプリにGoogle Driveの読み取り権限を渡す」のように第三者アプリへAPIアクセス権限を渡す仕組みです。OpenID Connect(OIDC)はOAuthを土台に認証を標準化した拡張で、「Googleでログイン」はOIDCで実現されています。標準化されたプロトコルなので、自前で実装せずAuth0 / Firebase Auth / Cognito / Okta等に委譲するのが現代の主流です。
フローは用途別に分かれますが、新規実装ではAuthorization Code+PKCEがほぼ一択です。認可コードをブラウザ経由で受け取りサーバー側でトークンと交換する2段構えで、PKCEにより途中で認可コードを横取りされても攻撃者がトークンに交換できません。
| フロー | 用途 |
|---|---|
| Authorization Code+PKCE | SPA・モバイル・Webアプリ(標準) |
| Client Credentials | サーバ間通信(ユーザーが介在しない) |
| Device Code | TV・CLIなど入力困難な端末 |
| 非推奨(古い情報源に注意) |
どう選べばいいのか ― ドメイン構造で決める
判断軸はシンプルです。従来型Webアプリ・SPA+API(同一ドメイン)ならサーバセッション(Cookie)が既定です。「SPAだからJWT」は誤解で、httpOnly Cookieで十分安全です。マイクロサービス・横断認証ならJWT+Refresh Token。外部ログイン連携(Google・GitHub等)はOIDCでAuth0 / Firebase Authに委譲。社内システム(SSO必要)はOIDC+SSO基盤(Okta / Entra ID)で人事異動の権限変更も一元管理します。
どの方式でも、Cookie属性の設定が安全性を大きく左右します。「HttpOnly(JSから読めない)+Secure(HTTPSのみ)+SameSite=Lax(CSRF防止)」はWebアプリの最低ラインです。
// 推奨: Cookie で受け渡し(XSS から守られる)
res.cookie("session", token, {
httpOnly: true, // JS から読めない(XSS 対策)
secure: true, // HTTPS のみ送信
sameSite: "lax", // CSRF 対策
maxAge: 60 * 60 * 1000, // 1 時間
path: "/",
});
// 非推奨: localStorage 保存(XSS 一発で漏洩)
localStorage.setItem("token", token);
セッション・トークン有効期限の数値Gate
※ 2026年4月時点の業界相場値です。
「なんとなく」で決めると必ず脆弱性を生むため、具体的な数値基準を最初に決めます。
| 設定項目 | 推奨値 |
|---|---|
| Access Token(JWT)有効期限 | 15分 |
| Refresh Token(httpOnly Cookie)有効期限 | 14〜30日+Rotation有効化 |
| Session IDエントロピー | 128bit以上 |
| JWT署名アルゴリズム | RS256 / EdDSA(none は絶対禁止) |
| CSRF対策 | SameSite=Lax+CSRFトークンの二重防御 |
JWTの none アルゴリズムは署名検証なしで偽造可能になるため絶対に許可しません(2018年に複数ライブラリで脆弱性が多発)。Refresh Tokenは使用ごとに新しい値を発行(Rotation)し、古い値が再利用されたらセッション全失効という運用が現代の定石です。
3つのシナリオで考える
個人開発・スタートアップの場合
ClerkやAuth.js、Supabase Authへの委譲一択だと思います。セッション管理・トークンローテーション・OAuth連携を自前で書くのは、個人開発で最も時間を溶かす罠だからです。方式としてはhttpOnly Cookieのサーバセッションが既定で、「SPAだからJWT」という誤解に乗らないことが重要になります。
中小SaaSの場合
Auth0やCognitoを使いつつ、同一ドメインならサーバセッション、サービス分割時はJWTとRefresh Token Rotationの組み合わせ、という使い分けになります。Access Tokenは15分、Refresh Tokenは14〜30日にRotation有効化という数値Gateを守り、B2B向けにはSAMLやOIDC対応をIdP選定時に確認しておいてください。
大企業の場合
OIDCでSSO基盤(OktaやEntra ID)へ統合するのが前提となります。こうしておけば人事異動の権限変更を一元管理できますし、退職者アカウントの放置も構造的に防げるのです。逆に、社内システムごとに独立した認証DBを作るのはセキュリティ事故の温床ですので、絶対に避けるべきです。
AI判断軸 ― AIが書ける領域と落とす箇所
AI駆動開発が前提になると、セッション実装は「AIが正しく書ける領域」と「明示しないと省略される領域」がきっぱり分かれます。
AIが正しく書ける実装と、落とす箇所
AIはOAuth 2.0 Authorization Code+PKCEのフロー全体を正確に書けます。RFC 7636に忠実なcode_verifierの生成からtokenエンドポイントへのPOSTまで、ほぼ間違えません。問題は運用面の設定で、SameSite=Lax の未設定、Refresh Token Rotationの省略、ログアウト時にサーバ側のRefresh Tokenを失効させるAPIの欠落、HttpOnly の付け忘れがよく起きます。これらはAIが「書けない」のではなく、明示的に指示しないと省略する箇所です。機能テストでは見つからない(認証フローが動いていてもセキュリティ設定が甘い状態はパスしてしまう)ため、レビューチェックリストと静的解析で拾う前提の設計が必要です。
IDaaS SDK利用時のAI活用パターン
Auth.js(旧NextAuth)・Clerk・Firebase Authのような認証SDKを使う場合、ドキュメントが充実して学習データも豊富なため、AIの生成精度は非常に高くなります。自前のセッション管理を書かせるより、SDKのセットアップとミドルウェア設定を書かせる方が安全かつ正確です。
やってはいけないこと
セッション実装で事故る典型パターンは、どれもアカウント乗っ取り・成りすましに直結します。特に危険な6つに絞ります。
| 禁じ手 | なぜダメか → どうするか |
|---|---|
| JWTをlocalStorageに保存 | XSSで簡単に盗まれる → httpOnly Cookieに保管する |
| Cookie属性を設定しない | XSS・盗聴・CSRFの全てが成立する → HttpOnly+Secure+SameSiteを明示する |
| 「SPAだからJWT」でCookieセッションを避ける | 同一ドメインならCookieの方が安全かつシンプル → ドメイン構造で選ぶ |
| JWTの失効設計なし | 漏洩時に無効化できない → 短命Access+Refresh Token Rotationにする |
| Implicit Flow / Password Grantを新規採用 | 2020年以降は非推奨 → Authorization Code+PKCEにする |
| ログアウト時にCookie削除のみ | サーバ側のRefresh Tokenが生き残る → 失効APIを実装する |
認証方式そのもの(パスワード保存・MFA・Passkey)の鬼門は別カテゴリ「セキュリティアーキテクチャ」を参照してください。
筆者メモ ― 「JWTなら新しくてイケてる」の錯覚
2010年代後半のSPAブームで広まった誤解に、「SPAなんだからJWTをlocalStorageに入れるのが現代的」という刷り込みがあります。同一ドメインで動く普通のWebアプリでも、なぜかCookieセッションを避けてJWTに飛び付く事例が後を絶ちませんでした。結果として、XSS一発で全ユーザーのJWTが流出し、しかもJWTの性質上即時失効できないため、攻撃者は有効期限まで好き放題という事例が繰り返し報告されています。
JWTはマイクロサービス横断・外部連携のように「ステートレスでないと成立しない場面」で光る技術で、同一ドメインの普通のWebアプリには過剰装備です。「新しい方が正しい」は認証では通用しません。枯れた方式が選ばれ続けるのは理由があるのです。
決めるべきこと — 自分のプロジェクトでの答えは?
以下の項目について、自分のプロジェクトの答えを1〜2文で言語化してみてください。曖昧なまま着手すると、必ず後から「なぜそう決めたんだっけ」が問われます。
- セッション方式(サーバセッション / JWT / ハイブリッド)
- Cookie属性(HttpOnly / Secure / SameSite)
- Access Token有効期限 / Refresh Token Rotation
- JWT署名アルゴリズム(RS256 / EdDSA、
none禁止) - OAuthフロー(Authorization Code+PKCEほぼ一択)
- ログアウト時の処理(失効APIの実装)
言語化した答えはADRとして残します。書き方の具体例は以下の記事で解説しています。
この記事に関連する記事
まとめ
本記事は認証・セッション設計について、サーバセッション vs JWT・OAuth/OIDC・Cookie属性まで含めて解説しました。如何だったでしょうか。
同一ドメインはCookie、横断はJWT、外部連携はOIDC。Cookie属性は明示、JWTは短命+Refresh Token Rotation、OAuthはPKCE一択。これがソフトウェアアーキテクチャレベルでのセッション運用の現実解です。
これで「ソフトウェアアーキテクチャ」カテゴリ全8記事が完結しました。次回からは「アプリケーションアーキテクチャ」カテゴリに入り、クラス設計・ドメインロジック・命名規約・エラーハンドリングを解説していきます。
シリーズ目次に戻る → 『生成AI時代のアーキテクチャ超入門』の歩き方
本記事で扱った内容の詳細は OAuth 2.0 も合わせて参考にしてください。
それでは次の記事も閲覧いただけると幸いです。
📚 シリーズ:生成AI時代のアーキテクチャ超入門(30/95)
