Server Components とは
Server Components は、サーバ側で実行されるReactコンポーネントです。
ブラウザではなくサーバで実行されるため、データベースアクセス、セッション確認、外部API呼び出しをブラウザに直接見せずに行えます。
export default async function Page() {
const data = await fetchDataOnServer();
return <main>{data.title}</main>;
}
認証設計では、この「サーバ側で実行される」という性質が重要です。
クライアント側で session を読む構成
従来のSPAでは、クライアントコンポーネントがログイン状態を取得し、APIを呼ぶ構成がよくありました。
"use client";
export function Dashboard() {
const token = localStorage.getItem("access_token");
useEffect(() => {
fetch("https://api.example.com/orders", {
headers: { Authorization: `Bearer ${token}` },
});
}, []);
return <div>...</div>;
}
この構成では、ブラウザがアクセストークンを持つ必要があります。
サーバ側で session を読む構成
Server Componentsでは、サーバ側でsessionを読み、必要なデータを取得してから画面を返せます。
import { redirect } from "next/navigation";
import { auth } from "@/auth";
export default async function DashboardPage() {
const session = await auth();
if (!session) {
redirect("/login");
}
const orders = await getOrders(session.user.id);
return <OrderList orders={orders} />;
}
この場合、ブラウザにaccess tokenを渡す必要がありません。必要な認証情報はサーバ側で使い、ブラウザへは表示に必要なデータだけを返します。
ポイント: Server Components の認証上の価値は、トークンをブラウザに渡さずにデータ取得できることです。
props で token を渡してはいけない
Server Componentsで取得したaccess tokenを、Client Componentへpropsで渡すと意味がありません。
// 悪い例
export default async function Page() {
const accessToken = await getAccessToken();
return <ClientWidget accessToken={accessToken} />;
}
Client Componentへ渡したpropsは、ブラウザ側にシリアライズされます。つまり、access tokenをブラウザに公開しているのと同じです。
Client Componentへ渡すのは、表示に必要な最小限のデータにします。
Server Components だけでは更新処理は完結しない
Server Componentsは表示やデータ取得に向いています。一方、フォーム送信やデータ更新には Server Actions や Route Handlers を使います。
認証チェックは、更新処理の中でも必ず行います。
"use server";
export async function updateProfile(formData: FormData) {
const session = await auth();
if (!session) throw new Error("Unauthorized");
await updateProfileInDb(session.user.id, formData);
}
表示時にログインチェックしていても、更新処理側のチェックを省略してはいけません。
Middleware との関係
Middlewareで未ログインユーザーをリダイレクトすることはできます。
しかし、Middlewareは最終防衛線ではありません。
Server Component内でも、次のようにsessionを確認します。
const session = await auth();
if (!session) redirect("/login");
多層防御として、入口でも守り、本体でも守るという考え方です。
まとめ
Server Componentsは、認証情報をブラウザに出さずにサーバ側で処理するために役立ちます。
- サーバ側でsessionを読める
- サーバ側でDBや外部APIを呼べる
- ブラウザにaccess tokenを渡さずに済む
- Client Componentへtokenをpropsで渡してはいけない
- 更新処理ではServer ActionsやRoute Handlers側でも認証チェックする
- Middlewareだけに頼らない
参考リソース
- 公式ドキュメント - Server Components と認証 - なぜサーバ側で session を読むのか を確認するための一次情報
次に読む記事
- Server Actions と Cookie 認証
- Next.js はなぜ BFF と相性がいいのか
- NextAuth / Auth.js で accessToken を session に載せてはいけない理由