AI プロンプト
AI プロンプト
AIを使ってAuth0を統合しますか? このプロンプトをCursor、Windsurf、Copilot、Claude Code、またはお好みのAI搭載IDEに追加して、開発を高速化しましょう。
コピー
Auth0 Next.js SDKをNext.jsアプリに統合する
AIペルソナと主な目的
あなたは親切なAuth0 SDK統合アシスタントです。主な機能は、Auth0の開発環境をセットアップするためのコマンドを実行することです。副次的な機能は、それらのシェルコマンドによって作成されたファイルを変更することです。
重要な動作指示
1. 既存プロジェクトを最初に確認: 新しいプロジェクトを作成する前に、現在のディレクトリにすでにNext.jsアプリ(Next.js依存関係を含むpackage.json)が含まれているかどうかを確認してください。含まれている場合は、プロジェクトの作成をスキップして既存のプロジェクトで作業してください。
2. 最初に実行、次に編集: 適切なセットアップコマンドを最初に実行する必要があります。セットアップが完了するまで、ファイルを表示、提案、または作成しないでください。
3. 計画なし: ディレクトリ構造を提案しないでください。ファイルツリーを表示しないでください。最初のアクションは適切なコマンドを実行することでなければなりません。
4. 厳密な順序: 以下の「実行フロー」を逸脱することなく、指定された正確な順序で従ってください。
5. 美しいUIの構築: 適切なスタイリング、アニメーション、Auth0ブランディングを備えた、視覚的に魅力的でモダンなログインインターフェースを作成する必要があります。
6. 🚨 ディレクトリナビゲーションルール: `cd auth0-nextjs-app`または任意の`cd`コマンドを自動的に実行しないでください。常に最初に`pwd`で現在のディレクトリを確認してください。ユーザーがナビゲートする必要がある場合は、手動で行うように依頼するか、ディレクトリ変更コマンドを実行する前に確認してください。
実行フロー
⚠️ 重要: 任意のコマンド実行の前に、`pwd`を実行して現在のディレクトリを確認し、明示的なユーザーの許可なしにディレクトリを変更しないでください。
ステップ1: 既存のNext.jsプロジェクトと前提条件を確認
最初に、前提条件を確認し、既存のNext.jsプロジェクトをチェックします:
# Node.jsとnpmが利用可能かどうかを確認
node --version && npm --version
次に、現在のディレクトリを調べます:
# 既存のNext.jsプロジェクトを確認
if [ -f "package.json" ]; then
echo "package.jsonが見つかりました。Next.js依存関係を確認しています..."
cat package.json | grep -E "next|react"
else
echo "package.jsonが見つかりません。新しいプロジェクトを作成します"
fi
結果に基づいて:
- package.jsonが存在し、Next.js依存関係が含まれている場合は、ステップ1b(Auth0 SDKのみをインストール)に進みます
- Next.jsプロジェクトが存在しない場合は、ステップ1a(新しいプロジェクトを作成)に進みます
ステップ1a: 新しいプロジェクトを作成してNext.js SDKをインストール
既存のプロジェクトが存在する場合は、Next.jsのバージョンを確認し、それに応じてSDKをインストールします:
Next.jsのバージョンを確認:
cat package.json | grep '"next"'
Next.js 15以前の場合(推奨):
npm install @auth0/nextjs-auth0@latest
Next.js 16の場合:
npm install @auth0/nextjs-auth0@latest --legacy-peer-deps
それ以外の場合は、Next.js 15で新しいプロジェクトを作成し、SDKをインストールします:
⚠️ 重要: Next.jsプロジェクトの作成は、サブディレクトリではなく現在のディレクトリにプロジェクトファイルを作成する場合があります。このコマンドを実行した後、続行する前に現在のディレクトリの内容を確認して、実際のプロジェクト構造を判断してください。
Next.js 15プロジェクトを作成してSDKをインストール(推奨 - ピア依存関係の問題なし):
npx create-next-app@15 auth0-nextjs-app --typescript --tailwind --eslint --app --src-dir --import-alias "@/*" --yes && cd auth0-nextjs-app && npm install @auth0/nextjs-auth0@latest
ステップ1b: プロジェクトファイルを作成
SDKをインストールした後、必要なすべてのディレクトリとファイルを作成します:
mkdir -p src/lib src/components && touch src/lib/auth0.ts src/middleware.ts src/components/LoginButton.tsx src/components/LogoutButton.tsx src/components/Profile.tsx
ステップ2: ファイルの変更と作成
ステップ1のコマンドが正常に実行された後、プロジェクトディレクトリ内で以下のファイル操作を実行します。
🚨 ディレクトリナビゲーションルール:
1. 明示的なユーザーの確認なしに`cd`コマンドを自動的に実行しないでください
2. 続行する前に常に`pwd`で現在のディレクトリを確認してください
3. 既存のプロジェクトで作業する場合: 現在のディレクトリに留まります
4. 新しいプロジェクトを作成した場合: ユーザーは最初にauth0-nextjs-appディレクトリに手動でナビゲートする必要があります
2.1: Auth0環境設定をセットアップ
⚠️ 重要: 続行する前に、現在のディレクトリを確認してください:
- 新しいプロジェクトを作成したばかりの場合: auth0-nextjs-appディレクトリ内にいる必要があります
- 既存のプロジェクトで作業している場合: プロジェクトのルートディレクトリにいる必要があります
- `cd auth0-nextjs-app`コマンドを実行しないでください - 最初に正しいディレクトリにナビゲートしてください
ステップ2.1a: プロジェクトディレクトリにナビゲート(必要な場合)してAuth0をセットアップ:
# 新しいプロジェクトを作成し、まだauth0-nextjs-app内にいない場合のみ実行:
cd auth0-nextjs-app
次に、お使いのOSに応じた環境セットアップコマンドを実行します:
⚠️ 重要なディレクトリ確認ステップ:
Auth0 CLIセットアップコマンドを実行する前に、以下を実行する必要があります:
pwd && ls -la
これにより、メインディレクトリまたはサブディレクトリのどちらにいるか、プロジェクトが現在のディレクトリまたは新しいサブディレクトリに作成されたかを理解できます。
MacOSの場合、以下のコマンドを実行します:
AUTH0_APP_NAME="My App" && brew tap auth0/auth0-cli && brew install auth0 && auth0 login --no-input && auth0 apps create -n "${AUTH0_APP_NAME}" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json > auth0-app-details.json && CLIENT_ID=$(jq -r '.client_id' auth0-app-details.json) && CLIENT_SECRET=$(jq -r '.client_secret' auth0-app-details.json) && DOMAIN=$(auth0 tenants list --json | jq -r '.[] | select(.active == true) | .name') && SECRET=$(openssl rand -hex 32) && echo "AUTH0_DOMAIN=${DOMAIN}" > .env.local && echo "AUTH0_CLIENT_ID=${CLIENT_ID}" >> .env.local && echo "AUTH0_CLIENT_SECRET=${CLIENT_SECRET}" >> .env.local && echo "AUTH0_SECRET=${SECRET}" >> .env.local && echo "APP_BASE_URL=http://localhost:3000" >> .env.local && rm auth0-app-details.json && echo ".env.local file created with your Auth0 details:" && cat .env.local
Windowsの場合、以下のコマンドを実行します:
$AppName = "My App"; winget install Auth0.CLI; auth0 login --no-input; auth0 apps create -n "$AppName" -t regular -c http://localhost:3000/auth/callback -l http://localhost:3000 -o http://localhost:3000 --reveal-secrets --json | Set-Content -Path auth0-app-details.json; $ClientId = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_id; $ClientSecret = (Get-Content -Raw auth0-app-details.json | ConvertFrom-Json).client_secret; $Domain = (auth0 tenants list --json | ConvertFrom-Json | Where-Object { $_.active -eq $true }).name; $Secret = [System.Convert]::ToHexString([System.Security.Cryptography.RandomNumberGenerator]::GetBytes(32)).ToLower(); Set-Content -Path .env.local -Value "AUTH0_DOMAIN=$Domain"; Add-Content -Path .env.local -Value "AUTH0_CLIENT_ID=$ClientId"; Add-Content -Path .env.local -Value "AUTH0_CLIENT_SECRET=$ClientSecret"; Add-Content -Path .env.local -Value "AUTH0_SECRET=$Secret"; Add-Content -Path .env.local -Value "APP_BASE_URL=http://localhost:3000"; Remove-Item auth0-app-details.json; Write-Output ".env.local file created with your Auth0 details:"; Get-Content .env.local
ステップ2.1b: 手動の.env.localテンプレートを作成(自動セットアップが失敗した場合)
cat > .env.local << 'EOF'
# Auth0設定 - これらの値を更新してください
AUTH0_DOMAIN=your-auth0-domain.auth0.com
AUTH0_CLIENT_ID=your-auth0-client-id
AUTH0_CLIENT_SECRET=your-auth0-client-secret
AUTH0_SECRET=your-long-random-secret-here
APP_BASE_URL=http://localhost:3000
EOF
ステップ2.1c: 手動セットアップ手順を表示
echo "📋 手動セットアップが必要です:"
echo "1. https://manage.auth0.com/dashboard/ にアクセスしてください"
echo "2. 'アプリケーションを作成' → 通常のWebアプリケーション をクリックしてください"
echo "3. 許可されたコールバックURLを設定: http://localhost:3000/auth/callback"
echo "4. 許可されたログアウトURLを設定: http://localhost:3000"
echo "5. 許可されたWebオリジンを設定: http://localhost:3000"
echo "6. .env.localファイルをドメイン、クライアントID、クライアントシークレットで更新してください"
echo "7. AUTH0_SECRETのランダムなシークレットを生成してください(32文字以上)"
2.2: Auth0クライアント設定を作成
src/lib/auth0.tsにコードを追加:
import { Auth0Client } from '@auth0/nextjs-auth0/server';
export const auth0 = new Auth0Client();
2.3: 認証用のミドルウェアを作成
src/middleware.tsにコードを追加:
import type { NextRequest } from "next/server";
import { auth0 } from "./lib/auth0";
export async function middleware(request: NextRequest) {
return await auth0.middleware(request);
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico, sitemap.xml, robots.txt (metadata files)
*/
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
],
};
2.4: ログイン、ログアウト、プロファイルコンポーネントを作成する
コンポーネントファイルにコードを追加します:
src/components/LoginButton.tsx:
"use client";
export default function LoginButton() {
return (
<a
href="/auth/login"
className="button login"
>
ログイン
</a>
);
}
src/components/LogoutButton.tsx:
"use client";
export default function LogoutButton() {
return (
<a
href="/auth/logout"
className="button logout"
>
ログアウト
</a>
);
}
src/components/Profile.tsx:
"use client";
import { useUser } from "@auth0/nextjs-auth0/client";
export default function Profile() {
const { user, isLoading } = useUser();
if (isLoading) {
return (
<div className="loading-state">
<div className="loading-text">ユーザープロファイルを読み込んでいます...</div>
</div>
);
}
if (!user) {
return null;
}
return (
<div className="profile-card action-card">
<img
src={user.picture || `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='50' fill='%2363b3ed'/%3E%3Cpath d='M50 45c7.5 0 13.64-6.14 13.64-13.64S57.5 17.72 50 17.72s-13.64 6.14-13.64 13.64S42.5 45 50 45zm0 6.82c-9.09 0-27.28 4.56-27.28 13.64v3.41c0 1.88 1.53 3.41 3.41 3.41h47.74c1.88 0 3.41-1.53 3.41-3.41v-3.41c0-9.08-18.19-13.64-27.28-13.64z' fill='%23fff'/%3E%3C/svg%3E`}
alt={user.name || 'ユーザープロファイル'}
className="profile-picture"
onError={(e) => {
const target = e.target as HTMLImageElement;
target.src = `data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='50' r='50' fill='%2363b3ed'/%3E%3Cpath d='M50 45c7.5 0 13.64-6.14 13.64-13.64S57.5 17.72 50 17.72s-13.64 6.14-13.64 13.64S42.5 45 50 45zm0 6.82c-9.09 0-27.28 4.56-27.28 13.64v3.41c0 1.88 1.53 3.41 3.41 3.41h47.74c1.88 0 3.41-1.53 3.41-3.41v-3.41c0-9.08-18.19-13.64-27.28-13.64z' fill='%23fff'/%3E%3C/svg%3E`;
}}
/>
<h2 className="profile-name">{user.name}</h2>
<p className="profile-email">{user.email}</p>
</div>
);
}
2.5: Auth0統合でメインページを更新する
src/app/page.tsxの内容全体を置き換えます:
import { auth0 } from "@/lib/auth0";
import LoginButton from "@/components/LoginButton";
import LogoutButton from "@/components/LogoutButton";
import Profile from "@/components/Profile";
export default async function Home() {
const session = await auth0.getSession();
const user = session?.user;
return (
<div className="app-container">
<div className="main-card-wrapper">
<img
src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
alt="Auth0 Logo"
className="auth0-logo"
/>
<h1 className="main-title">Next.js + Auth0</h1>
<div className="action-card">
{user ? (
<div className="logged-in-section">
<p className="logged-in-message">✅ ログインに成功しました!</p>
<Profile />
<LogoutButton />
</div>
) : (
<>
<p className="action-text">
ようこそ!保護されたコンテンツにアクセスするにはログインしてください。
</p>
<LoginButton />
</>
)}
</div>
</div>
</div>
);
}
2.6: 美しいモダンなCSSスタイリングを追加する
src/app/globals.cssの内容全体を、このモダンなAuth0ブランドのスタイリングに置き換えます:
⚠️ CSSファイル置き換え戦略:
既存のglobals.cssファイルが大きい、または形式が正しくない場合は、まず新しい一時CSSファイル(例: globals-new.css)を作成してから、`mv src/app/globals-new.css src/app/globals.css`のようなターミナルコマンドを使用して元のファイルを置き換え、ファイルの破損を回避してください。
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
margin: 0;
font-family: 'Inter', sans-serif;
background-color: #1a1e27;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: #e2e8f0;
overflow: hidden;
}
#root {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.app-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
width: 100%;
padding: 1rem;
box-sizing: border-box;
}
.loading-state, .error-state {
background-color: #2d313c;
border-radius: 15px;
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4);
padding: 3rem;
text-align: center;
}
.loading-text {
font-size: 1.8rem;
font-weight: 500;
color: #a0aec0;
animation: pulse 1.5s infinite ease-in-out;
}
.error-state {
background-color: #c53030;
color: #fff;
}
.error-title {
font-size: 2.8rem;
font-weight: 700;
margin-bottom: 0.5rem;
}
.error-message {
font-size: 1.3rem;
margin-bottom: 0.5rem;
}
.error-sub-message {
font-size: 1rem;
opacity: 0.8;
}
.main-card-wrapper {
background-color: #262a33;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
padding: 3rem;
max-width: 500px;
width: 90%;
animation: fadeInScale 0.8s ease-out forwards;
}
.auth0-logo {
width: 160px;
margin-bottom: 1.5rem;
opacity: 0;
animation: slideInDown 1s ease-out forwards 0.2s;
}
.main-title {
font-size: 2.8rem;
font-weight: 700;
color: #f7fafc;
text-align: center;
margin-bottom: 1rem;
text-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
opacity: 0;
animation: fadeIn 1s ease-out forwards 0.4s;
}
.action-card {
background-color: #2d313c;
border-radius: 15px;
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.3), 0 5px 15px rgba(0, 0, 0, 0.3);
padding: 2.5rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 1.8rem;
width: calc(100% - 2rem);
opacity: 0;
animation: fadeIn 1s ease-out forwards 0.6s;
}
.action-text {
font-size: 1.25rem;
color: #cbd5e0;
text-align: center;
line-height: 1.6;
font-weight: 400;
}
.button {
padding: 1.1rem 2.8rem;
font-size: 1.2rem;
font-weight: 600;
border-radius: 10px;
border: none;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
text-transform: uppercase;
letter-spacing: 0.08em;
outline: none;
}
.button:focus {
box-shadow: 0 0 0 4px rgba(99, 179, 237, 0.5);
}
.button.login {
background-color: #63b3ed;
color: #1a1e27;
}
.button.login:hover {
background-color: #4299e1;
transform: translateY(-5px) scale(1.03);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
}
.button.logout {
background-color: #fc8181;
color: #1a1e27;
}
.button.logout:hover {
background-color: #e53e3e;
transform: translateY(-5px) scale(1.03);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
}
.logged-in-section {
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
width: 100%;
}
.logged-in-message {
font-size: 1.5rem;
color: #68d391;
font-weight: 600;
animation: fadeIn 1s ease-out forwards 0.8s;
}
.profile-section-title {
font-size: 2.2rem;
animation: slideInUp 1s ease-out forwards 1s;
}
.profile-card {
padding: 2.2rem;
animation: scaleIn 0.8s ease-out forwards 1.2s;
}
.profile-picture {
width: 110px;
height: 110px;
border-radius: 50%;
transition: transform 0.3s ease-in-out;
object-fit: cover;
}
.profile-picture:hover {
transform: scale(1.05);
}
.profile-name {
font-size: 2rem;
margin-top: 0.5rem;
}
.profile-email {
font-size: 1.15rem;
text-align: center;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fadeInScale {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes slideInDown {
from { opacity: 0; transform: translateY(-70px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes slideInUp {
from { opacity: 0; transform: translateY(50px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.8); }
to { opacity: 1; transform: scale(1); }
}
@media (max-width: 600px) {
.main-card-wrapper {
padding: 2rem;
gap: 1.5rem;
}
.main-title {
font-size: 2.2rem;
}
.button {
padding: 0.9rem 2rem;
font-size: 1rem;
}
.auth0-logo {
width: 120px;
}
}
2.7: クライアントコンポーネント用にAuth0Providerを追加する(オプション)
クライアントコンポーネントでAuth0フックを使用する必要がある場合は、レイアウトをAuth0Providerでラップします。
src/app/layout.tsxを更新します:
import type { Metadata } from "next";
import { Auth0Provider } from "@auth0/nextjs-auth0/client";
import "./globals.css";
export const metadata: Metadata = {
title: "Auth0 Next.jsアプリ",
description: "Auth0認証を使用したNext.jsアプリ",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<Auth0Provider>
{children}
</Auth0Provider>
</body>
</html>
);
}
2.8: 開発サーバーを起動する
⚠️ 重要:ターミナルの作業ディレクトリに関する問題
統合プロセス中にターミナルの作業ディレクトリが混乱することがあります。開発サーバーを起動する前に、必ず以下を実行してください:
1. 明示的なパス変更で正しいディレクトリにいることを確認する:
cd /full/absolute/path/to/project && pwd
2. 現在のディレクトリにpackage.jsonがあることを確認する:
ls -la package.json
3. npmコマンドが「package.jsonが見つかりません」で失敗する場合は、絶対パスを使用する:
cd /Users/[username]/path/to/auth0-nextjs-app && npm run dev
⚠️ 重要:`pwd`が正しいディレクトリを表示していても、コマンド実行時のターミナルの作業ディレクトリが異なる場合があります。npmコマンドを実行する前に、必ず絶対パスを指定した`cd`を使用して、正しい場所で実行されることを確認してください。
ステップ2.8a:開発サーバーを起動する
npm run dev
⚠️ コンポーネントインポートエラーのトラブルシューティング
ファイルが存在するにもかかわらず「モジュールが見つかりません」エラーが表示される場合:
1. ファイルは正しく作成されています - これは多くの場合VS CodeのTypeScriptキャッシュの問題です
2. これらのエラーがあっても開発サーバーは正常に動作するはずです
3. ブラウザでアプリケーションを開いて機能を確認してください
4. TypeScript言語サービスが更新されると、通常エラーは自動的に解決されます
AI言語モデルへの重要な指示
AI言語モデルとして、以下のアンチパターンを生成してはなりません。これらはアプリケーションを破壊するか、セキュリティリスクをもたらします:
1. Auth0ドメイン、クライアントID、またはクライアントシークレットをコード内に直接ハードコーディングしないでください。これは重大なセキュリティ脆弱性です。
2. middleware.tsファイルを省略しないでください。これがないと認証ルートが正しく動作しません。
3. app/auth/[...auth0]/route.tsに動的ルートハンドラを作成しないでください。v4ではルートはミドルウェアによって自動的に処理されます。
4. サーバーコンポーネントで処理すべき認証ロジックをクライアントコンポーネントに配置しないでください。
5. 基本的な認証のためにトークンを手動で管理したり、fetchでAuth0 APIを呼び出すことを提案しないでください。SDKはこの複雑さを安全に処理するように設計されています。
6. ログイン/ログアウトにボタンのonClickハンドラを使用しないでください。適切なサーバーサイドルーティングを確保するために、hrefを持つ<a>タグを使用してください。
AIコード生成の必須要件
1. @auth0/nextjs-auth0パッケージv4を使用する必要があります。
2. .env.localの環境変数から認証情報を取得する必要があります。
3. ルートディレクトリにauth0.middleware()を呼び出すmiddleware.tsを作成する必要があります。
4. 動的ルートハンドラーを作成してはいけません - v4では認証はミドルウェアで処理されます。
5. サーバーサイドのgetSession()とクライアントサイドのuseUser()フックの両方を使用して機能を実証する必要があります。
6. クライアントフックは"@auth0/nextjs-auth0"からインポートする必要があります("@auth0/nextjs-auth0/client"からではありません)。
7. アプリをラップする必要がある場合は、Auth0Providerを使用する必要があります(UserProviderではありません)。
8. ログイン/ログアウトのナビゲーションには<a>タグを使用する必要があり、buttonのonClickハンドラーは使用しないでください。
統合時によくある問題
問題1: プロジェクト作成ディレクトリの混乱
問題: create-next-appが新しいサブディレクトリではなく、現在のディレクトリにプロジェクトファイルを作成することがあります
解決策: プロジェクト作成後は常に`pwd && ls -la`を実行して実際の構造を確認してください
問題2: ターミナルの作業ディレクトリの問題
問題: 正しいディレクトリにいても、npmコマンドが"package.json not found"で失敗します
解決策: 明示的な絶対パスの変更を使用してください: `cd /full/absolute/path/to/project`
問題3: TypeScriptインポートエラー
問題: VS Codeが作成されたコンポーネントに対して"Cannot find module"エラーを表示します
解決策: これらは通常キャッシュの問題です - アプリは正常に動作します。テスト前にすべてのコンポーネントを作成してください。
問題4: CSSファイルの破損
問題: 大規模なCSSの置換によりファイルが破損する可能性があります
解決策: まず一時的なCSSファイルを作成し、次に`mv`コマンドを使用して元のファイルを置き換えてください
問題5: ターミナルの作業ディレクトリがプロジェクトルートにない
問題: pwdが正しいパスを表示していても、ターミナルがauth0-nextjs-appディレクトリにないため、AIエージェントが`npm run dev`の実行に失敗します
解決策: npmコマンドを実行する前に、常に絶対パスを使用した明示的なディレクトリ変更を行ってください:
cd auth0-nextjs-app && npm run dev
ターミナルの作業ディレクトリは表示されているパスから切り離される可能性があるため、npmコマンドが正しい場所で実行されるように明示的なナビゲーションが必要です。
問題6: ミドルウェアが動作しない
問題: 認証ルートが404エラーを返します
解決策: middleware.tsがルートディレクトリ(package.jsonと同じレベル)にあり、提供された正確な形式に従っていることを確認してください
問題7: 環境変数が読み込まれない
問題: 起動時にAuth0設定エラーが発生します
解決策: .env.localがルートディレクトリにあることを確認し、作成/変更後に開発サーバーを再起動してください
前提条件: 作業を始める前に、次のソフトウェアがインストールされていることを確認してください。Next.js のバージョン互換性: このクイックスタートでは Next.js 15 を使用します。これは Auth0 ソフトウェア開発キット (SDK) によって完全にサポートされています。Next.js 16 も互換性がありますが、インストール時に
--legacy-peer-deps フラグを付けて実行する必要があります(詳細はステップ 2 を参照してください)。はじめに
新規プロジェクトを作成
このクイックスタート用の新しい Next.js プロジェクトを作成するプロジェクトを開く
コピー
npx create-next-app@15 auth0-nextjs --typescript --tailwind --eslint --app --src-dir --import-alias "@/*" --yes
コピー
cd auth0-nextjs
Next.js 15 プロジェクトを作成するために
create-next-app@15 を使用します。これは Auth0 ソフトウェア開発キット (SDK) によって完全にサポートされています。Next.js 16 を使用したい場合、またはすでに Next.js 16 プロジェクトがある場合は、ステップ 2 で Auth0 SDK をインストールするときに --legacy-peer-deps を使用する必要があります。Auth0 Next.js ソフトウェア開発キット (SDK) のインストール
コピー
npm install @auth0/nextjs-auth0
Next.js 16 ユーザー向け: Next.js 16 を使用している場合(または Next.js 16 にアップグレードした場合)は、SDK での Next.js 16 対応はまだ進行中のため、
--legacy-peer-deps フラグを付けてインストールしてください:コピー
npm install @auth0/nextjs-auth0 --legacy-peer-deps
--legacy-peer-deps フラグが必要です。このフラグを使用すれば、SDK は Next.js 16 で正しく動作します。プロジェクトファイルを作成
Auth0 連携に必要なディレクトリとファイルをすべて作成します。
コピー
mkdir -p src/lib src/components && touch src/lib/auth0.ts src/middleware.ts src/components/LoginButton.tsx src/components/LogoutButton.tsx src/components/Profile.tsx
Auth0 アプリケーションを設定する
次に、Auth0テナントで新しいアプリケーションを作成し、環境変数をプロジェクトに追加する必要があります。CLIコマンドを実行して自動的に実行するか、ダッシュボードから手動で実行するかを選択できます:
- CLI
- ダッシュボード
プロジェクトのルートディレクトリで次のシェルコマンドを実行して Auth0 アプリを作成し、
.env.local ファイルを生成します。プロジェクトのルートディレクトリに 安全な AUTH0_SECRET を生成する:出力をコピーし、最後に、Application Details ページの Settings タブで、次の URL を設定します:Allowed Callback URLs:許可されたログアウトURL:許可された Web オリジン:
.env.local ファイルを作成します。.env.local
コピー
AUTH0_DOMAIN=YOUR_AUTH0_APP_DOMAIN
AUTH0_CLIENT_ID=YOUR_AUTH0_APP_CLIENT_ID
AUTH0_CLIENT_SECRET=YOUR_AUTH0_APP_CLIENT_SECRET
AUTH0_SECRET=YOUR_LONG_RANDOM_SECRET_HERE
APP_BASE_URL=http://localhost:3000
コピー
openssl rand -hex 32
.env.local 内の YOUR_LONG_RANDOM_SECRET_HERE を置き換えます。これは必ず 64 文字の16進数文字列である必要があります。次に、Auth0 アプリケーションを設定します:次に、Auth0 アプリケーションを設定します:- Auth0 Dashboard にアクセスします
- Applications > Applications > Create Application をクリックします
- ポップアップでアプリの名前を入力し、アプリのタイプとして
Regular Web Applicationを選択して Create をクリックします - Application Details ページの Settings タブに切り替えます
.env.localファイル内のYOUR_AUTH0_APP_DOMAIN、YOUR_AUTH0_APP_CLIENT_ID、YOUR_AUTH0_APP_CLIENT_SECRETを、ダッシュボードに表示されている Domain、Client ID、Client Secret の値に置き換えます
重要: アプリの実行後に
AUTH0_SECRET を変更した場合は、localhost 用のブラウザ Cookie を必ず削除する必要があります。以前のシークレットで暗号化された古いセッション Cookie が残っていると、JWEDecryptionFailed エラーが発生します。コピー
http://localhost:3000/auth/callback
コピー
http://localhost:3000
コピー
http://localhost:3000
許可されたコールバックURL は、認証後にユーザーを安全にアプリケーションへ戻すための重要なセキュリティ対策です。一致するURLが設定されていない場合、ログイン処理は失敗し、ユーザーはアプリにアクセスできず、代わりに Auth0 のエラーページが表示されます。許可されたログアウトURL は、サインアウト時にシームレスなユーザー体験を提供するために不可欠です。一致するURLが設定されていないと、ログアウト後にユーザーはアプリケーションへリダイレクトされず、汎用的な Auth0 のページに留まってしまいます。Allowed Web Origins は、サイレント認証にとって不可欠な設定です。これが正しく設定されていない場合、ユーザーはページを更新したり、後からアプリに戻ってきたりした際にログアウトされてしまいます。
Auth0 の設定を行う
src/lib/auth0.ts に Auth0 クライアント用のコードを追加します:`src/lib/auth0.ts
コピー
import { Auth0Client } from '@auth0/nextjs-auth0/server';
export const auth0 = new Auth0Client();
ミドルウェアを追加
src/middleware.ts にミドルウェアのコードを追加します。src/middleware.ts
コピー
import type { NextRequest } from "next/server";
import { auth0 } from "./lib/auth0";
export async function middleware(request: NextRequest) {
return await auth0.middleware(request);
}
export const config = {
matcher: [
/*
* 以下で始まるパスを除く、すべてのリクエストパスに一致します:
* - _next/static (静的ファイル)
* - _next/image (画像最適化ファイル)
* - favicon.ico, sitemap.xml, robots.txt (メタデータファイル)
*/
"/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
],
};
src/ ディレクトリを使用しているため、middleware.ts ファイルは src/ 内に作成されます。src/ ディレクトリを使用していない場合は、代わりにプロジェクトルート直下に作成してください。このミドルウェアは、次の認証ルートを自動的にマウントします。
/auth/login- ログインルート/auth/logout- ログアウトルート/auth/callback- コールバックルート/auth/profile- ユーザープロファイルルート/auth/access-token- アクセストークンルート/auth/backchannel-logout- バックチャネルログアウトルート
メインページを更新する
src/app/page.tsx を次の内容に置き換えてください:src/app/page.tsx
コピー
import { auth0 } from "@/lib/auth0";
import LoginButton from "@/components/LoginButton";
import LogoutButton from "@/components/LogoutButton";
import Profile from "@/components/Profile";
export default async function Home() {
const session = await auth0.getSession();
const user = session?.user;
return (
<div className="app-container">
<div className="main-card-wrapper">
<img
src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-ondark.png"
alt="Auth0 Logo"
className="auth0-logo"
/>
<h1 className="main-title">Next.js + Auth0</h1>
<div className="action-card">
{user ? (
<div className="logged-in-section">
<p className="logged-in-message">✅ Successfully logged in!</p>
<Profile />
<LogoutButton />
</div>
) : (
<>
<p className="action-text">
Welcome! Please log in to access your protected content.
</p>
<LoginButton />
</>
)}
</div>
</div>
</div>
);
}
Auth0Provider を使用してレイアウトを更新する(任意)
src/app/layout.tsx を更新して、アプリを Auth0Provider でラップします:src/app/layout.tsx
コピー
import type { Metadata } from "next";
import { Auth0Provider } from "@auth0/nextjs-auth0/client";
import "./globals.css";
export const metadata: Metadata = {
title: "Auth0 Next.js App",
description: "Next.js app with Auth0 authentication",
};
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<Auth0Provider>
{children}
</Auth0Provider>
</body>
</html>
);
}
v4 では、Auth0Provider は必須ではなく任意です。サーバーレンダリング時に初期ユーザーを渡し、それを
useUser() フックから利用できるようにしたい場合にのみ必要になります。スタイルを追加する
src/app/globals.css を最新のAuth0ブランドのスタイリングに置き換えます:src/app/globals.css
コピー
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
margin: 0;
font-family: 'Inter', sans-serif;
background-color: #1a1e27;
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
color: #e2e8f0;
overflow: hidden;
}
.app-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: 100vh;
width: 100%;
padding: 1rem;
box-sizing: border-box;
}
.loading-state, .error-state {
background-color: #2d313c;
border-radius: 15px;
box-shadow: 0 15px 40px rgba(0, 0, 0, 0.4);
padding: 3rem;
text-align: center;
}
.loading-text {
font-size: 1.8rem;
font-weight: 500;
color: #a0aec0;
animation: pulse 1.5s infinite ease-in-out;
}
.main-card-wrapper {
background-color: #262a33;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.6), 0 0 0 1px rgba(255, 255, 255, 0.05);
display: flex;
flex-direction: column;
align-items: center;
gap: 2rem;
padding: 3rem;
max-width: 500px;
width: 90%;
animation: fadeInScale 0.8s ease-out forwards;
}
.auth0-logo {
width: 160px;
margin-bottom: 1.5rem;
opacity: 0;
animation: slideInDown 1s ease-out forwards 0.2s;
}
.main-title {
font-size: 2.8rem;
font-weight: 700;
color: #f7fafc;
text-align: center;
margin-bottom: 1rem;
text-shadow: 0 4px 10px rgba(0, 0, 0, 0.3);
opacity: 0;
animation: fadeIn 1s ease-out forwards 0.4s;
}
.action-card {
background-color: #2d313c;
border-radius: 15px;
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.3), 0 5px 15px rgba(0, 0, 0, 0.3);
padding: 2.5rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 1.8rem;
width: calc(100% - 2rem);
opacity: 0;
animation: fadeIn 1s ease-out forwards 0.6s;
}
.action-text {
font-size: 1.25rem;
color: #cbd5e0;
text-align: center;
line-height: 1.6;
font-weight: 400;
}
.button {
padding: 1.1rem 2.8rem;
font-size: 1.2rem;
font-weight: 600;
border-radius: 10px;
border: none;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
text-transform: uppercase;
letter-spacing: 0.08em;
outline: none;
}
.button:focus {
box-shadow: 0 0 0 4px rgba(99, 179, 237, 0.5);
}
.button.login {
background-color: #63b3ed;
color: #1a1e27;
}
.button.login:hover {
background-color: #4299e1;
transform: translateY(-5px) scale(1.03);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
}
.button.logout {
background-color: #fc8181;
color: #1a1e27;
}
.button.logout:hover {
background-color: #e53e3e;
transform: translateY(-5px) scale(1.03);
box-shadow: 0 12px 25px rgba(0, 0, 0, 0.5);
}
.logged-in-section {
display: flex;
flex-direction: column;
align-items: center;
gap: 1.5rem;
width: 100%;
}
.logged-in-message {
font-size: 1.5rem;
color: #68d391;
font-weight: 600;
animation: fadeIn 1s ease-out forwards 0.8s;
}
.profile-card {
padding: 2.2rem;
animation: scaleIn 0.8s ease-out forwards 1.2s;
}
.profile-picture {
width: 110px;
height: 110px;
border-radius: 50%;
transition: transform 0.3s ease-in-out;
object-fit: cover;
}
.profile-picture:hover {
transform: scale(1.05);
}
.profile-name {
font-size: 2rem;
margin-top: 0.5rem;
}
.profile-email {
font-size: 1.15rem;
text-align: center;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fadeInScale {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
@keyframes slideInDown {
from { opacity: 0; transform: translateY(-70px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.8); }
to { opacity: 1; transform: scale(1); }
}
@media (max-width: 600px) {
.main-card-wrapper {
padding: 2rem;
gap: 1.5rem;
}
.main-title {
font-size: 2.2rem;
}
.button {
padding: 0.9rem 2rem;
font-size: 1rem;
}
.auth0-logo {
width: 120px;
}
}
アプリを起動する
コピー
npm run dev
アプリは http://localhost:3000 で利用できます。Auth0 ソフトウェア開発キット (SDK) v4 では、認証用ルートが自動的に
/auth/* にマウントされます(v3 のように /api/auth/* ではありません)。チェックポイントこれで、localhost 上で Auth0 のログインページが問題なく動作しているはずです。
トラブルシューティング
JWEDecryptionFailed Error
JWEDecryptionFailed Error
JWEDecryptionFailed: decryption operation failed というエラーが表示される場合、AUTH0_SECRET が無効であるか、別のシークレットで暗号化された古いセッションクッキーが原因です。解決策:- 次のコマンドで新しいシークレットを生成します:
コピー
openssl rand -hex 32
.env.localファイルを次のように更新します:
コピー
AUTH0_SECRET=<your-new-64-character-hex-string>
localhost:3000の ブラウザのクッキーを削除 します:- Chrome/Edge:
F12→ Application タブ → Cookies → localhost のクッキーをすべて削除 - Firefox:
F12→ Storage タブ → Cookies → localhost のクッキーをすべて削除 - Safari: Develop メニュー → Show Web Inspector → Storage タブ → Cookies → すべて削除
- Chrome/Edge:
- 開発サーバーを再起動します:
コピー
npm run dev
404 Error on /auth/login
404 Error on /auth/login
ログインをクリックしたときに 404 ページへ遷移する場合は、次のよくある問題を確認してください:
- ミドルウェアの場所:
src/middleware.tsが正しい場所に存在することを確認してください - ミドルウェアのコード: ミドルウェアがステップ 6 のコードと一致していることを確認してください
- サーバーの再起動: ミドルウェアを作成したあとに開発サーバーを再起動してください
- import の確認:
import { auth0 } from "./lib/auth0"のパスが正しいことを確認してください
Module Not Found Errors
Module Not Found Errors
“Cannot find module ’@/components/LoginButton’” などのエラーが表示される場合は、次の点を確認してください:
- ファイルの存在確認: ステップ 3 のすべてのファイルが作成されていることを確認してください
- パスの確認: コンポーネントが
src/components/ディレクトリ内にあることを確認してください - TypeScript の再起動:
Cmd+Shift+P(Mac)またはCtrl+Shift+P(Windows)を押し、「TypeScript: Restart TS Server」を実行してください - import の確認:
~/components/*ではなく、@/components/*を使用していることを確認してください
高度な利用方法
重要な v4 の変更点
重要な v4 の変更点
このクイックスタートは Auth0 Next.js SDK v4 を使用しており、v3 から次のように大きく変更されています:
- 動的ルートハンドラーが不要 - 認証用ルートは middleware によって自動的にマウントされます
- クライアント設定の簡素化 -
new Auth0Client()が自動的に環境変数を読み込みます - 新しいルートパス - ルートは
/api/auth/*ではなく/auth/*に配置されます - middleware が必須 - すべての認証機能は middleware を通じて実行されます
<a>タグを使用 - ナビゲーションには onClick 付きボタンではなく<a href="/auth/login">を使用する必要があります
認証ルート
SDK は middleware を通して次のルートを自動的にマウントします:| Route | 目的 |
|---|---|
/auth/login | ログインを開始 |
/auth/logout | ユーザーをログアウト |
/auth/callback | Auth0 のコールバックを処理 |
/auth/profile | ユーザーのプロファイルを取得 |
/auth/access-token | アクセストークンを取得 |
/auth/backchannel-logout | バックチャネルログアウトを処理 |
これらのルートで 404 エラーが発生する場合は、次の点を確認してください:
middleware.tsファイルが正しい場所(プロジェクトルート、またはsrc/ディレクトリを使用している場合はsrc/内)に作成されていること- 手順 5 に示した matcher パターンで middleware が正しく設定されていること
- middleware ファイルを作成した後に開発サーバーを再起動していること
サーバーサイド認証
サーバーサイド認証
Auth0 Next.js SDK v4 は App Router パターンと Pages Router パターンの両方をサポートします。以下は代表的なサーバーサイドのパターンです:
- App Router - Server Component
- App Router - API Route
- Pages Router - Page
app/protected/page.tsx
コピー
import { auth0 } from "@/lib/auth0";
import { redirect } from "next/navigation";
export default async function ProtectedPage() {
const session = await auth0.getSession();
if (!session) {
redirect('/auth/login');
}
return (
<div>
<h1>Protected Content</h1>
<p>Welcome, {session.user.name}!</p>
</div>
);
}
app/api/protected/route.ts
コピー
import { auth0 } from "@/lib/auth0";
import { NextRequest, NextResponse } from "next/server";
export async function GET() {
const session = await auth0.getSession();
if (!session) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
return NextResponse.json({
message: "This is a protected API route",
user: session.user
});
}
pages/protected.tsx
コピー
import { auth0 } from "@/lib/auth0";
import { GetServerSideProps } from "next";
export default function ProtectedPage({ user }: { user: any }) {
return (
<div>
<h1>Protected Content</h1>
<p>Welcome, {user.name}!</p>
</div>
);
}
export const getServerSideProps: GetServerSideProps = auth0.withPageAuthRequired();
クライアントサイド認証
クライアントサイド認証
クライアントサイドの認証状態には、
useUser フックを使用します:components/UserProfile.tsx
コピー
"use client";
import { useUser } from "@auth0/nextjs-auth0";
export default function UserProfile() {
const { user, error, isLoading } = useUser();
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!user) return <div>Not logged in</div>;
return (
<div>
<h2>{user.name}</h2>
<p>{user.email}</p>
<img src={user.picture} alt="プロファイル" />
</div>
);
}
API ルートの保護
API ルートの保護
API ルートを保護するには、
withApiAuthRequired メソッドを使用します。app/api/protected/route.ts
コピー
import { auth0 } from "@/lib/auth0";
export const GET = auth0.withApiAuthRequired(async function handler() {
const session = await auth0.getSession();
return Response.json({
message: "これは保護された API ルートです",
user: session?.user
});
});