Contents
Auth0 アカウント作成とアプリケーション登録
Auth0 テナントを作成し、Next.js 用シングルページアプリケーション(SPA)を登録するだけで、認証に必要な Domain / Client ID / Client Secret が取得できます。これらはローカル開発時の .env.local だけでなく、Vercel の環境変数にも必須です。
必要になる情報と取得手順
Auth0 コンソール左メニューから Applications → Create Application を選び、以下を設定してください。
| 項目 | 説明 |
|---|---|
| Domain | your-tenant.auth0.com の形で表示されるテナントドメイン |
| Client ID | フロントエンドから公開しても安全な識別子 |
| Client Secret | サーバー側でのみ使用する機密情報(.env.local に保存) |
ポイント:App Router ではサーバーコンポーネントが認証情報を直接扱うことはできません。必ず環境変数から取得し、SDK が内部で処理します。
コールバック URL とログアウト URL の設定
| 設定項目 | 推奨値 |
|---|---|
| Allowed Callback URLs | http://localhost:3000/api/auth/callback(ローカル)https://your-app.vercel.app/api/auth/callback(本番) |
| Allowed Logout URLs | http://localhost:3000/ https://your-app.vercel.app/ |
設定ミスがあると Invalid callback URL エラーになるため、必ず正確に記述してください。
Next.js プロジェクトへの Auth0 SDK インストールと基本設定
公式パッケージ @auth0/nextjs-auth0 は v3 系で TypeScript と App Router にフル対応しています。SSR・CSR どちらでもシームレスにユーザー情報を取得できるよう設計されています。
SDK のインストール(v3 系)
|
1 2 3 4 5 6 |
# npm npm install @auth0/nextjs-auth0@^3.0 # yarn yarn add @auth0/nextjs-auth0@^3.0 |
注:過去のドキュメントで
v2.xと記載されていることがありますが、2026 年現在は v3 系 が主流です。古い情報と混同しないようご注意ください。
環境変数の定義
プロジェクトルートに .env.local を作成し、以下を設定します(取得した値で置き換えてください)。
|
1 2 3 4 5 6 7 |
# .env.local AUTH0_SECRET=YOUR_RANDOM_64_BYTE_HEX # 例: openssl rand -hex 32 AUTH0_BASE_URL=http://localhost:3000 # 本番は Vercel の URL に変更 AUTH0_ISSUER_BASE_URL=https://your-tenant.auth0.com AUTH0_CLIENT_ID=YOUR_CLIENT_ID AUTH0_CLIENT_SECRET=YOUR_CLIENT_SECRET |
Vercel デプロイ時は、Settings > Environment Variables で同名の変数を Production・Preview・Development にすべて追加してください。
認証ガードと API ルーティングの実装
Auth0 が提供するハンドラ /api/auth/[...auth0] を作成すれば、ログイン・コールバック・ログアウトのエンドポイントが自動生成されます。加えて、SSR ページや Middleware で認証ガードを設定できます。
API ハンドラの実装例(App Router 用)
|
1 2 3 4 5 6 |
// app/api/auth/[...auth0]/route.ts import { handleAuth } from '@auth0/nextjs-auth0'; export const GET = handleAuth(); export const POST = handleAuth(); // 必要に応じてエイリアス |
handleAuth() が内部で login, callback, logout などのルートを生成します。個別にカスタマイズしたい場合は以下をインポートしてください。
|
1 2 3 4 5 6 |
import { handleLogin, handleCallback, handleLogout, } from '@auth0/nextjs-auth0'; |
SSR ページでの認証チェック(withPageAuthRequired)
withPageAuthRequired は getServerSideProps の代替として、サーバー側で自動的にセッションを取得し未認証時はリダイレクトします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// app/dashboard/page.tsx (Server Component) import { withPageAuthRequired } from '@auth0/nextjs-auth0'; import type { Metadata } from 'next'; export const metadata: Metadata = { title: 'Dashboard', }; export default withPageAuthRequired(async function Dashboard({ user }) { // `user` はサーバー側で取得済みのユーザー情報 return ( <section> <h1>ダッシュボードへようこそ</h1> <p>{user?.name} さん、今日も頑張りましょう!</p> </section> ); }); |
Middleware による保護(Edge Runtime)
|
1 2 3 4 5 6 7 8 |
// middleware.ts import { auth } from '@auth0/nextjs-auth0/edge'; export default auth({ // 認証が必要なパスを列挙 routes: [{ path: '/dashboard', methods: ['GET'] }], }); |
Middleware は Edge Runtime で実行されるため、リクエスト受信直後に認証チェックが走り、未認証ユーザーは即座にログインページへリダイレクトします。
Next.js 13+ App Router と Server Component での Auth0 活用
App Router では Server Component と Client Component が明確に分かれます。useUser フックは クライアントコンポーネントのみ で使用でき、サーバーコンポーネントでは getSession を直接呼び出す必要があります。
サーバーコンポーネントからユーザー情報を取得するヘルパー
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// lib/auth.ts import { getSession } from '@auth0/nextjs-auth0/server'; import type { NextRequest, NextResponse } from 'next/server'; /** * Server Component 用ユーティリティ * - `request` と `response` は Edge Runtime でも利用可能 */ export async function getUser( request: Request, response: Response ) { const session = await getSession(request, response); return session?.user ?? null; } |
重要:
@auth0/nextjs-auth0/serverのgetSessionは サーバー側だけ 呼び出すことが前提です。クライアントコンポーネントで同関数を使用するとビルドエラーになります。
Server Component で認可ロジックと子コンポーネントへのデータ受け渡し
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
// app/profile/page.tsx (Server Component) import { redirect } from 'next/navigation'; import { getUser } from '@/lib/auth'; import ClientOnlyProfile from '@/components/ClientOnlyProfile'; export default async function ProfilePage({ request, response, }: { request: Request; response: Response; }) { const user = await getUser(request, response); if (!user) { // 未認証ならログインページへリダイレクト redirect('/api/auth/login'); } return ( <section> <h1>マイプロフィール</h1> <p>{user?.name} さんのメール: {user?.email}</p> {/* クライアント側でインタラクティブに動かしたい UI */} <ClientOnlyProfile user={user!} /> </section> ); } |
クライアントコンポーネントで useUser を使用する例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
// components/ClientOnlyProfile.tsx 'use client'; import { useUser } from '@auth0/nextjs-auth0/client'; import type { UserProfile } from '@/types'; interface Props { user: UserProfile; // Server Component から受け取った確定データ } export default function ClientOnlyProfile({ user }: Props) { const { isLoading, error } = useUser(); // オプションで再取得も可能 if (isLoading) return <p>ロード中…</p>; if (error) return <p>エラーが発生しました: {error.message}</p>; return ( <div> {/* サーバーから受け取ったデータをそのまま表示 */} <pre>{JSON.stringify(user, null, 2)}</pre> </div> ); } |
- Server Component が認可ロジックと初期データ取得を担い、
- Client Component は
useUserで最新の認証状態(トークンリフレッシュ等)を監視しつつ UI を構築します。
この分離により、SSR 時点で正しいユーザー情報が確定し、クライアント側でもリアルタイムな状態変化に追従できます。
ローカル開発・テストと Vercel への自動デプロイ
認証は外部サービスとの連携が必須のため、ローカルだけでなく CI/CD パイプラインでも検証しておくことが重要です。以下では Playwright(E2E) と Jest(ユニット) を用いたテスト例と、Vercel デプロイ時の注意点を紹介します。
Playwright でのエンドツーエンドテスト
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// tests/auth.e2e.ts import { test, expect } from '@playwright/test'; test('ログイン→ダッシュボード遷移が成功すること', async ({ page }) => { await page.goto('http://localhost:3000'); await page.click('text=ログイン'); // Auth0 のホストにリダイレクト → テスト用アカウントで認証 await page.fill('#username', 'e2e-test@example.com'); await page.fill('#password', 'SecurePass!123'); await page.click('button[name="submit"]'); // コールバック後、ダッシュボードが表示されることを確認 await expect(page).toHaveURL(/\/dashboard/); await expect(page.locator('text=ようこそ')).toBeVisible(); }); |
Jest でのセッション取得ユニットテスト
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// __tests__/session.test.ts import { getSession } from '@auth0/nextjs-auth0/server'; import { createMocks } from 'node-mocks-http'; test('有効なクッキーから正しいユーザー情報が取得できる', async () => { const { req, res } = createMocks({ headers: { cookie: 'appSession=valid-session-token' }, }); const session = await getSession(req as any, res as any); expect(session?.user).toMatchObject({ email: expect.stringContaining('@'), }); }); |
CI に組み込む例(GitHub Actions)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
name: CI on: push: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: '20' - run: npm ci - run: npm run build # Next.js のビルド - run: npx jest --coverage - run: npx playwright test |
Vercel 環境変数とプレビュー環境での確認手順
- Settings > Environment Variables に
.env.localと同名のキーをProduction,Preview,Developmentすべてに設定。 - プレビュー URL が生成されたら、ブラウザで
/api/auth/loginにアクセスし Auth0 のログイン画面が表示されるか確認。 - Allowed Callback URLs にプレビュー用の
https://<preview-id>.vercel.app/api/auth/callbackを追加しておくと、プレビュー環境でも正常にコールバックできます。
典型的なエラーと対策
| エラー | 原因 | 解決策 |
|---|---|---|
| Invalid callback URL | プレビュー・本番の URL が Auth0 に未登録 | Allowed Callback URLs に全デプロイ先を列挙 |
| Session cookie too large | JWT が大きくなり Cookie 上限超過 | session.cookie.maxAge を短めに設定し、Refresh Token のみ保持 |
| SSR と CSR でユーザー状態が不一致 | サーバー側でセッション取得失敗 | withPageAuthRequired や Middleware で必ず SSR 時点でもチェック |
| CORS エラー(プレビュー) | Vercel プレビューのドメインが Auth0 の CORS リストに未登録 | Allowed Web Origins に https://*.vercel.app を追加 |
まとめ
- Auth0 テナントとアプリケーションを作成し、Domain・Client ID・Client Secret を取得したら
.env.localと Vercel の環境変数に設定する。 - @auth0/nextjs-auth0 v3 系 をインストールし、
app/api/auth/[...auth0]/route.tsにハンドラを作成すれば認証エンドポイントが自動生成される。 - サーバーコンポーネントでは
useUserを使用せず、@auth0/nextjs-auth0/serverのgetSessionでユーザー情報を取得するヘルパー (getUser) を作成する。 - 認証ガードは
withPageAuthRequired(SSR)と Middleware(Edge Runtime)の組み合わせで実装し、未認証アクセスを確実に防止できる。 - Playwright と Jest によるテストを CI に組み込み、プレビュー環境でも Auth0 のコールバック URL を正しく設定すればデプロイ時のトラブルを回避できる。
これらの手順とベストプラクティスに従えば、最新の Next.js App Router と Auth0 SDK v3 系で 安全・高速・スケーラブル な認証基盤が構築できます。ぜひ実務に取り入れて、開発フローを一段階上げてみてください。