Skip to content

セッション管理と session_secret の仕組み

このドキュメントでは、Webアプリケーションにおけるセッション管理の基本概念と、本プロジェクトの Bonus Website (/website) で session_secret が必要となる理由、およびその仕組みについて解説します。

1. セッション管理とは?

HTTP通信は**ステートレス(状態を持たない)**プロトコルです。つまり、Aのページを見た直後にBのページを見ても、サーバー側からは「同じ人が連続してアクセスしてきた」とは認識できません。

これを解決し、「ログインしている状態」などの情報を保持するための仕組みがセッション管理です。

基本的な流れ

  1. ログイン時: ユーザーが正しいID/パスワード(本プロジェクトでは OAuth API を介した OAuth認証)を提供すると、サーバーはメモリやデータベースに「このユーザーはログイン済みである」という情報(セッションデータ)を作成します。
  2. Cookieの発行: サーバーは、作成したセッションデータに紐づく**一意の推測不可能なID(セッションID)**を生成し、HTTPレスポンスの Set-Cookie ヘッダーを使ってユーザーのブラウザに送信します。
  3. 次回以降のアクセス: ブラウザは、同じドメインへのリクエストの際に、保存しておいたCookie(セッションID)を自動的にサーバーへ送信します。
  4. セッションの復元: サーバーは受け取ったセッションIDを元にデータを検索し、「これはログイン済みのあのユーザーからのリクエストだ」と状態を復元します。

2. なぜ session_secret が必要なのか?

セッション管理において、セッションIDは通常Cookieとしてブラウザに保存されます。ここで問題となるのがCookieの改ざんです。

もし悪意のあるユーザーが自分のCookie(セッションID)を、他の誰かのセッションIDに書き換えて送信した場合、サーバーがそれをそのまま信じてしまうと、**セッションハイジャック(なりすまし)**が成立してしまいます。

これを防ぐための強力な対策が、**Cookieへの署名(Signature)です。 session_secret は、この署名を生成・検証するための暗号的な鍵(パスワード)**として機能します。

署名による改ざん検知の仕組み

  1. セッションIDの生成: サーバーがランダムな文字列(例: abc123xyz)を生成します。
  2. デジタル署名の計算: サーバーは、生成したセッションIDとあらかじめ設定された session_secret を組み合わせて、ハッシュ関数(HMACなど)を使って署名を生成します。
    • 例: Cookie = "abc123xyz." + HMAC("abc123xyz", session_secret)
  3. 検証: クライアントから送られてきたCookieを受け取った際、サーバーは再び手元の session_secret を使って送られてきたセッションID部分から署名を再計算します。
  4. 一致確認: 再計算した署名と、送られてきた署名が一致すれば、「このCookieはサーバー自身が発行したものであり、改ざんされていない」と保証できます。

もし攻撃者がセッションIDを書き換えた場合、正しい session_secret を知らない限り正しい署名を再計算できないため、サーバー側の検証で不一致となり、不正なアクセスとして弾くことができます。

3. 本プロジェクト (Bonus Website) での導入経緯

本プロジェクトにおける session_secret の採用は、Bonus Website が単なる静的なHTML配信から、「OAuth APIを用いた OAuth認証付きのアプリケーション」へと進化したことが直接の理由です。

srcs/requirements/bonus/website/server.js において、以下のミドルウェアが使用されています。

javascript
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 ファイルから安全に読み込む設計を採用しています。
  • 定期的なローテーション: 万が一シークレットが漏洩したリスクに備え、定期的に値を変更(ローテーション)することが推奨されます。(※シークレットを変更すると、既存のすべてのセッションが無効になり、全ユーザーが再ログインを求められます)。

Released under the MIT License.