0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

初心者でもわかる!Firebase Authenticationと安全なセッション管理の全体像

0
Posted at

はじめに

Web アプリを作るとき、ユーザーが「ログイン」したことを安全に認識し続ける仕組みは必須です。
Firebase Authentication は、メール・パスワードや Google・GitHub などの外部プロバイダーを簡単に統合できるサービスですが、認証情報だけでは「セッション」の維持はできません。

本記事では、Firebase Authentication と セッション管理 の全体像を初心者向けに解説し、実装例を TypeScript(Next.js)で示します。

1. 認証とセッションの違い

用語 役割 代表的なデータ
認証 (Authentication) ユーザーが誰かを確認する ID トークン、リフレッシュトークン
セッション (Session) 認証状態を継続的に保持する セッションクッキー、サーバー側セッションストア

Firebase が提供するのは ID トークン と リフレッシュトークン です。
ID トークンは JWT 形式で、クライアント側に保存して API へ付与できますが、有効期限が 1 時間程度と短いです。
そこで、セッション管理 でトークンを安全に保持し、期限切れ時に自動でリフレッシュする仕組みが必要になります。

2. 推奨アーキテクチャ

┌─────────────┐        ┌─────────────────────┐
│   クライアント│        │      Next.js API      │
│ (React/Next)│───►───►│  (Node.js Runtime)   │
└─────▲───────┘        └───────▲───────────────┘
      │                        │
      │  Firebase Auth SDK     │
      ▼                        │
┌─────────────┐   HTTP Only Cookie   │
│  Firebase   │◄───────────────────────┘
│  Auth Server│
└─────────────┘
  1. クライアントは Firebase SDK でサインインし、getIdToken() で取得した ID トークンを Next.js の API へ POST。
  2. APIはトークンを検証し、サーバー側で HTTP Only Cookie に セッション ID を設定。
  3. 以降のリクエストは Cookie だけで認証が通り、サーバーは Cookie のセッション ID からユーザー情報を取得。
  4. トークン有効期限が切れたら、サーバー側でリフレッシュトークンを使って新しい ID トークンを取得し、Cookie を更新。

この構成のメリットは:

  • XSS 対策: HTTP Only Cookie なので JavaScript から直接アクセスできない。
  • SSR 対応: Next.js の getServerSideProps でも Cookie が読めるため、サーバーサイドレンダリング時にユーザー情報を取得可能。
  • トークンの自動リフレッシュ: サーバーがリフレッシュトークンを管理するので、クライアント側で期限切れを意識しなくて済む。

3. 実装ステップ

3.1 Firebase プロジェクトの作成と設定

  1. Firebase コンソールでプロジェクトを作成。
  2. Authentication → 「サインイン方法」から「メール/パスワード」や「Google」などを有効化。
  3. 「プロジェクト設定」→「一般」から Web アプリの Firebase 設定オブジェクトを取得。

3.2 Next.js に Firebase SDK を導入

npm install firebase @firebase/app @firebase/auth

lib/firebase.ts に初期化コードを書きます。

// lib/firebase.ts
import { initializeApp, getApps } from "firebase/app";
import { getAuth } from "firebase/auth";

const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
  projectId: "YOUR_PROJECT_ID",
  // 他の項目は省略
};

export const firebaseApp = !getApps().length ? initializeApp(firebaseConfig) : getApps()[0];
export const auth = getAuth(firebaseApp);

3.3 サインイン UI(クライアント側)

// pages/login.tsx
import { signInWithEmailAndPassword, getIdToken } from "firebase/auth";
import { auth } from "../lib/firebase";
import { useState } from "react";

export default function Login() {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  const handleLogin = async (e: React.FormEvent) => {
    e.preventDefault();
    const userCred = await signInWithEmailAndPassword(auth, email, password);
    const idToken = await getIdToken(userCred.user);
    // API エンドポイントへトークン送信
    await fetch("/api/sessionLogin", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ idToken }),
    });
    // ログイン後はトップページへリダイレクト
    window.location.href = "/";
  };

  return (
    <form onSubmit={handleLogin}>
      <input type="email" value={email} onChange={e => setEmail(e.target.value)} placeholder="email" required />
      <input type="password" value={password} onChange={e => setPassword(e.target.value)} placeholder="password" required />
      <button type="submit">ログイン</button>
    </form>
  );
}

3.4 API でセッション Cookie を設定

Next.js の API ルート pages/api/sessionLogin.ts を作成します。
ここでは firebase-admin を使って ID トークンを検証し、セッション ID を生成して Cookie に保存します。

npm install firebase-admin cookie
// pages/api/sessionLogin.ts
import type { NextApiRequest, NextApiResponse } from "next";
import admin from "firebase-admin";
import cookie from "cookie";

if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.applicationDefault(),
  });
}

// セッションの有効期間(例: 7 日)
const SESSION_COOKIE_MAX_AGE = 60 * 60 * 24 * 7; // 秒

export default async (req: NextApiRequest, res: NextApiResponse) => {
  if (req.method !== "POST") {
    res.status(405).end();
    return;
  }

  const { idToken } = req.body;
  if (!idToken) {
    res.status(400).json({ error: "idToken is required" });
    return;
  }

  try {
    // ID トークンを検証し、カスタムセッションを作成
    const decoded = await admin.auth().verifyIdToken(idToken);
    const sessionCookie = await admin.auth().createSessionCookie(idToken, {
      expiresIn: SESSION_COOKIE_MAX_AGE * 1000,
    });

    // HTTP Only Cookie に保存
    const serialized = cookie.serialize("session", sessionCookie, {
      httpOnly: true,
      secure: process.env.NODE_ENV === "production",
      maxAge: SESSION_COOKIE_MAX_AGE,
      path: "/",
      sameSite: "lax",
    });

    res.setHeader("Set-Cookie", serialized);
    res.status(200).json({ status: "ok" });
  } catch (error) {
    console.error("Session creation error:", error);
    res.status(401).json({ error: "Unauthorized" });
  }
};

3.5 サーバーサイドでユーザー情報を取得

pages/_middleware.ts(Next.js 12 以前)や middleware.ts(Next.js 13+)で Cookie を検証し、req.user に情報を付与します。

// middleware.ts (Next.js 13)
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import admin from "firebase-admin";

if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.applicationDefault(),
  });
}

export async function middleware(req: NextRequest) {
  const sessionCookie = req.cookies.get("session")?.value;
  if (!sessionCookie) {
    return NextResponse.next();
  }

  try {
    const decoded = await admin.auth().verifySessionCookie(sessionCookie, true);
    // カスタムヘッダーにユーザー情報を埋め込む例
    const res = NextResponse.next();
    res.headers.set("x-user-id", decoded.uid);
    return res;
  } catch {
    // 無効なセッションは削除
    const res = NextResponse.redirect(new URL("/login", req.url));
    res.headers.set("Set-Cookie", "session=; Max-Age=0; Path=/");
    return res;
  }
}

getServerSideProps からはヘッダー x-user-id を読むことで、認証済みユーザーだけのページを簡単に作れます。

4. まとめ

  • Firebase Authentication は認証トークンの取得を簡素化し、外部プロバイダーも統一的に扱える。
  • セッション管理 はサーバー側で HTTP Only Cookie を使い、XSS に強い構成を取るのがベストプラクティス。
  • Next.js と firebase-admin の組み合わせで、SSR でもシームレスにユーザー情報を取得でき、開発者体験が向上する。

実際に手を動かすと、認証フローとセッション管理がどのように連携するかが体感できるはずです。ぜひ自分のプロジェクトに取り入れてみてください。


詳しい手順はこちら → https://felixstudio0.gumroad.com/?utm_source=qiita&utm_medium=github_actions&utm_campaign=2026-q1&utm_content=qiita-footer

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?