セッション管理と session_secret の仕組み
このドキュメントでは、Webアプリケーションにおけるセッション管理の基本概念と、本プロジェクトの Bonus Website (/website) で session_secret が必要となる理由、およびその仕組みについて解説します。
1. セッション管理とは?
HTTP通信は**ステートレス(状態を持たない)**プロトコルです。つまり、Aのページを見た直後にBのページを見ても、サーバー側からは「同じ人が連続してアクセスしてきた」とは認識できません。
これを解決し、「ログインしている状態」などの情報を保持するための仕組みがセッション管理です。
基本的な流れ
- ログイン時: ユーザーが正しいID/パスワード(本プロジェクトでは OAuth API を介した OAuth認証)を提供すると、サーバーはメモリやデータベースに「このユーザーはログイン済みである」という情報(セッションデータ)を作成します。
- Cookieの発行: サーバーは、作成したセッションデータに紐づく**一意の推測不可能なID(セッションID)**を生成し、HTTPレスポンスの
Set-Cookieヘッダーを使ってユーザーのブラウザに送信します。 - 次回以降のアクセス: ブラウザは、同じドメインへのリクエストの際に、保存しておいたCookie(セッションID)を自動的にサーバーへ送信します。
- セッションの復元: サーバーは受け取ったセッションIDを元にデータを検索し、「これはログイン済みのあのユーザーからのリクエストだ」と状態を復元します。
2. なぜ session_secret が必要なのか?
セッション管理において、セッションIDは通常Cookieとしてブラウザに保存されます。ここで問題となるのがCookieの改ざんです。
もし悪意のあるユーザーが自分のCookie(セッションID)を、他の誰かのセッションIDに書き換えて送信した場合、サーバーがそれをそのまま信じてしまうと、**セッションハイジャック(なりすまし)**が成立してしまいます。
これを防ぐための強力な対策が、**Cookieへの署名(Signature)です。 session_secret は、この署名を生成・検証するための暗号的な鍵(パスワード)**として機能します。
署名による改ざん検知の仕組み
- セッションIDの生成: サーバーがランダムな文字列(例:
abc123xyz)を生成します。 - デジタル署名の計算: サーバーは、生成したセッションIDとあらかじめ設定された
session_secretを組み合わせて、ハッシュ関数(HMACなど)を使って署名を生成します。- 例:
Cookie = "abc123xyz." + HMAC("abc123xyz", session_secret)
- 例:
- 検証: クライアントから送られてきたCookieを受け取った際、サーバーは再び手元の
session_secretを使って送られてきたセッションID部分から署名を再計算します。 - 一致確認: 再計算した署名と、送られてきた署名が一致すれば、「このCookieはサーバー自身が発行したものであり、改ざんされていない」と保証できます。
もし攻撃者がセッションIDを書き換えた場合、正しい session_secret を知らない限り正しい署名を再計算できないため、サーバー側の検証で不一致となり、不正なアクセスとして弾くことができます。
3. 本プロジェクト (Bonus Website) での導入経緯
本プロジェクトにおける session_secret の採用は、Bonus Website が単なる静的なHTML配信から、「OAuth APIを用いた OAuth認証付きのアプリケーション」へと進化したことが直接の理由です。
srcs/requirements/bonus/website/server.js において、以下のミドルウェアが使用されています。
const session = require('express-session');
app.use(session({
secret: SESSION_SECRET || 'inception_bonus_secret',
resave: false,
saveUninitialized: false,
cookie: {
secure: false,
maxAge: 24 * 60 * 60 * 1000 // 24 hours
}
}));express-session パッケージは、上記で解説した「Cookieの署名による改ざん保護」を標準で行う設計になっており、仕様として secret オプションにセッションシークレットを渡すことが必須とされています。
この設定が存在することで、Nginxの背後で動作するExpressサーバーは、安全にOAuth APIのOAuth認証状態を維持し、認可されたユーザーにのみVitePressのドキュメント(/website 内のコンテンツ)を提供する仕組みが完成しています。
4. セキュリティ上のベストプラクティス
- 強固な文字列を使用する: 推測されやすい文字列(パスワードなど)は使用せず、長くてランダムな文字列(例:
openssl rand -hex 32で生成したもの)を使用します。 - ソースコードにハードコードしない:
.envファイルや Docker Secrets などの仕組みを使って、環境変数やセキュアなファイルから読み込むようにします。本プロジェクトでは、Docker Compose のsecretsを用いて、外部のsession_secret.txtファイルから安全に読み込む設計を採用しています。 - 定期的なローテーション: 万が一シークレットが漏洩したリスクに備え、定期的に値を変更(ローテーション)することが推奨されます。(※シークレットを変更すると、既存のすべてのセッションが無効になり、全ユーザーが再ログインを求められます)。