Agent Skills by ALSEL
Anthropic Claudeソフトウェア開発⭐ リポ 2品質スコア 59/100

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

  1. Google Cloud Console にアクセスします
  2. OAuth 2.0 認証情報を作成します
  3. 認可済みリダイレクト URI を追加します: http://localhost:3000/api/auth/callback/google

Discord

  1. Discord Developer Portal にアクセスします
  2. アプリケーションと OAuth2 認証情報を作成します
  3. リダイレクト URI を追加します: http://localhost:3000/api/auth/callback/discord

GitHub

  1. GitHub Developer Settings にアクセスします
  2. OAuth アプリを作成します
  3. コールバック 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

関連スキル

汎用ソフトウェア開発⭐ リポ 39,967

doubt-driven-development

重要な判断はすべて、本番環境への展開前に新しい視点から対抗的レビューを実施します。速度より正確性が重要な場合、不慣れなコードを扱う場合、本番環境・セキュリティに関わるロジック・取り消し不可の操作など影響度が高い場合、または後でバグを修正するよりも今検証する方が効率的な場合に活用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 1,175

apprun-skills

TypeScriptを使用したAppRunアプリケーションのMVU設計に関する総合的なガイダンスが得られます。コンポーネントパターン、イベントハンドリング、状態管理(非同期ジェネレータを含む)、パラメータと保護機能を備えたルーティング・ナビゲーション、vistestを使用したテストに対応しています。AppRunコンポーネントの設計・レビュー、ルートの配線、状態フローの管理、AppRunテストの作成時に活用してください。

by yysun
OpenAIソフトウェア開発⭐ リポ 797

desloppify

コードベースのヘルスチェックと技術負債の追跡ツールです。コード品質、技術負債、デッドコード、大規模ファイル、ゴッドクラス、重複関数、コードスメル、命名規則の問題、インポートサイクル、結合度の問題についてユーザーが質問した場合に使用してください。また、ヘルススコアの確認、次の改善項目の提案、クリーンアップ計画の作成をリクエストされた際にも対応します。29言語に対応しています。

by Git-on-my-level
汎用ソフトウェア開発⭐ リポ 39,967

debugging-and-error-recovery

テストが失敗したり、ビルドが壊れたり、動作が期待と異なったり、予期しないエラーが発生したりした場合に、体系的な根本原因デバッグをガイドします。推測ではなく、根本原因を見つけて修正するための体系的なアプローチが必要な場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

test-driven-development

テスト駆動開発により実装を進めます。ロジックの実装、バグの修正、動作の変更など、あらゆる場面で活用できます。コードが正常に動作することを証明する必要がある場合、バグ報告を受けた場合、既存機能を修正する予定がある場合に使用してください。

by addyosmani
汎用ソフトウェア開発⭐ リポ 39,967

incremental-implementation

変更を段階的に実施します。複数のファイルに影響する機能や変更を実装する場合に使用してください。大量のコードを一度に書こうとしている場合や、タスクが一度では完結できないほど大きい場合に活用します。

by addyosmani
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: ftc8569 · ftc8569/ftcmetrics · ライセンス: MIT