nextauth
NextAuth.js v5の認証をOAuthプロバイダーとPrismaアダプターで設定できます。ログイン・ログアウト機能の実装、ルート保護、コンポーネント内でのセッションアクセス、OAuthプロバイダーの追加、認証関連の問題のトラブルシューティングが必要な場合に利用します。
description の原文を見る
Configure NextAuth.js v5 authentication with OAuth providers and Prisma adapter. Use when setting up login/logout, protecting routes, accessing sessions in components, adding OAuth providers, or troubleshooting authentication issues.
SKILL.md 本文
NextAuth.js v5 認証ガイド
NextAuth.js v5 (Auth.js) は FTC Metrics の認証ライブラリです。OAuthプロバイダー(Google、Discord、GitHub)とPrismaデータベースアダプターを使用してセッションの永続化を実現します。
クイックスタート
1. 依存関係のインストール
bun add next-auth@beta @auth/prisma-adapter
2. 認証設定の作成
src/lib/auth.ts を作成します:
import NextAuth from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
import Google from "next-auth/providers/google";
import Discord from "next-auth/providers/discord";
import GitHub from "next-auth/providers/github";
import { prisma } from "@ftcmetrics/db";
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [
Google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
Discord({
clientId: process.env.DISCORD_CLIENT_ID!,
clientSecret: process.env.DISCORD_CLIENT_SECRET!,
}),
GitHub({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
],
pages: {
signIn: "/login",
error: "/login",
},
callbacks: {
async session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
session: {
strategy: "database",
},
});
3. API ルートハンドラーの作成
src/app/api/auth/[...nextauth]/route.ts を作成します:
import { handlers } from "@/lib/auth";
export const { GET, POST } = handlers;
4. セッションプロバイダーの追加
src/components/providers.tsx を作成します:
"use client";
import { SessionProvider } from "next-auth/react";
export function Providers({ children }: { children: React.ReactNode }) {
return <SessionProvider>{children}</SessionProvider>;
}
src/app/layout.tsx でアプリをラップします:
import { Providers } from "@/components/providers";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}
Prismaスキーマの要件
データベースセッションを使用するNextAuthに必要なモデル:
model User {
id String @id @default(cuid())
name String?
email String? @unique
emailVerified DateTime? @map("email_verified")
image String?
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
accounts Account[]
sessions Session[]
@@map("users")
}
model Account {
id String @id @default(cuid())
userId String @map("user_id")
type String
provider String
providerAccountId String @map("provider_account_id")
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@map("accounts")
}
model Session {
id String @id @default(cuid())
sessionToken String @unique @map("session_token")
userId String @map("user_id")
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@map("sessions")
}
環境変数
.env に追加します:
# NextAuth
AUTH_SECRET="generate-with-openssl-rand-base64-32"
# Google OAuth
GOOGLE_CLIENT_ID="your-google-client-id"
GOOGLE_CLIENT_SECRET="your-google-client-secret"
# Discord OAuth
DISCORD_CLIENT_ID="your-discord-client-id"
DISCORD_CLIENT_SECRET="your-discord-client-secret"
# GitHub OAuth
GITHUB_CLIENT_ID="your-github-client-id"
GITHUB_CLIENT_SECRET="your-github-client-secret"
AUTH_SECRET を生成します:
openssl rand -base64 32
セッション管理パターン
サーバーコンポーネント(推奨)
サーバーコンポーネント内で auth() 関数を直接使用します:
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";
export default async function DashboardPage() {
const session = await auth();
if (!session?.user) {
redirect("/login");
}
return <div>Welcome, {session.user.name}</div>;
}
保護されたレイアウト
レイアウトレベルで認証を使用してルートグループ全体を保護します:
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";
export default async function ProtectedLayout({
children,
}: {
children: React.ReactNode;
}) {
const session = await auth();
if (!session?.user) {
redirect("/login");
}
return <>{children}</>;
}
クライアントコンポーネント
クライアントコンポーネント内で useSession フックを使用します:
"use client";
import { useSession, signOut } from "next-auth/react";
export function UserMenu() {
const { data: session, status } = useSession();
if (status === "loading") {
return <div>Loading...</div>;
}
if (!session?.user) {
return <a href="/login">Sign in</a>;
}
return (
<div>
<img src={session.user.image} alt={session.user.name} />
<span>{session.user.name}</span>
<button onClick={() => signOut({ callbackUrl: "/" })}>
Sign out
</button>
</div>
);
}
プロバイダーでサインイン
"use client";
import { signIn } from "next-auth/react";
export function LoginButtons() {
return (
<div>
<button onClick={() => signIn("google", { callbackUrl: "/dashboard" })}>
Continue with Google
</button>
<button onClick={() => signIn("discord", { callbackUrl: "/dashboard" })}>
Continue with Discord
</button>
<button onClick={() => signIn("github", { callbackUrl: "/dashboard" })}>
Continue with GitHub
</button>
</div>
);
}
セッションへのユーザー ID の追加
セッションコールバックはセッションをデータベースユーザー ID で拡張します:
callbacks: {
async session({ session, user }) {
if (session.user) {
session.user.id = user.id;
}
return session;
},
},
コンポーネントでユーザー ID にアクセスします:
// サーバーコンポーネント
const session = await auth();
const userId = session?.user?.id;
// クライアントコンポーネント
const { data: session } = useSession();
const userId = session?.user?.id;
OAuthプロバイダーのセットアップ
- Google Cloud Console にアクセスします
- OAuth 2.0 認証情報を作成します
- 認可済みリダイレクト URI を追加します:
http://localhost:3000/api/auth/callback/google
Discord
- Discord Developer Portal にアクセスします
- アプリケーションと OAuth2 認証情報を作成します
- リダイレクト URI を追加します:
http://localhost:3000/api/auth/callback/discord
GitHub
- GitHub Developer Settings にアクセスします
- OAuth アプリを作成します
- コールバック URL を追加します:
http://localhost:3000/api/auth/callback/github
よくある落とし穴
セッションが利用できない
- ルートレイアウトで
SessionProviderがアプリ全体をラップしていることを確認します - API ルートが
app/api/auth/[...nextauth]/route.tsに存在することを確認します
セッションからユーザー ID が見つからない
user.idを含めるセッションコールバックを追加します- データベース戦略を使用する場合、ユーザー情報は
tokenではなくuserパラメーターから取得されます
データベースセッションの問題
- Prismaスキーマが NextAuth の要件と完全に一致していることを確認します
onDelete: Cascadeをリレーションに使用してユーザー削除を処理します- スキーマ変更後に
prisma migrate devを実行します
OAuth コールバックエラー
- リダイレクト URI がプロバイダーコンソールと完全に一致していることを確認します
- 完全なパスを含めます:
/api/auth/callback/[provider] - 本番環境では URI を更新して HTTPS とドメインを使用します
AUTH_SECRET が見つからない
openssl rand -base64 32で生成します- 本番環境では必須で、開発環境では自動生成されます
TypeScript 型拡張
src/types/next-auth.d.ts でセッション型を拡張します:
import { DefaultSession } from "next-auth";
declare module "next-auth" {
interface Session {
user: {
id: string;
} & DefaultSession["user"];
}
}
ファイル構造リファレンス
packages/web/src/
lib/
auth.ts # NextAuth設定
components/
providers.tsx # SessionProviderラッパー
app/
api/auth/[...nextauth]/
route.ts # APIルートハンドラー
layout.tsx # Providersを使用したルートレイアウト
login/
page.tsx # ログインページ(サーバー)
login-form.tsx # OAuthボタン(クライアント)
dashboard/
layout.tsx # 保護されたレイアウト
page.tsx # セッションに auth() を使用
リファレンス
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- ftc8569
- リポジトリ
- ftc8569/ftcmetrics
- ライセンス
- MIT
- 最終更新
- 2026/2/24
Source: https://github.com/ftc8569/ftcmetrics / ライセンス: MIT
関連スキル
doubt-driven-development
重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。
apprun-skills
TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。
desloppify
コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。
debugging-and-error-recovery
テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。
test-driven-development
テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。
incremental-implementation
変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。