[…nextauth] とは?Next.jsでログイン認証を実装する方法【App Router対応】

[...nextauth] とは?Next.jsでログイン実装 API
[...nextauth] とは?Next.jsでログイン実装
この記事は約17分で読めます。

でじぼうです。

この記事では、Next.jsでログイン機能を作るときによく出てくる謎のファイル名
[...nextauth] について、App Router/Pages Router 両対応で丁寧に解説します。

でじぼう
でじぼう

この記事は下記の方がおすすめ!

  • […nextauth] ってなに?
  • […nextauth] って必要なの?
  • App Router/Pages Router の実装方法を知りたい!

Instagramフォロワー数9,500人を越える人気のもち・大福店 えにかいたもち

[…nextauth] ってなに?

[...nextauth] は、Next.jsの「キャッチオールルート」という仕組みを使った特別なファイルです。

これは、/api/auth/ 以下の複数のAPIエンドポイント(ログイン・ログアウトなど)を
1つのファイルでまとめて管理できる便利な仕組みです。

なぜ[…nextauth] は必要なの?

NextAuth.js を使うと、認証に関するさまざまなAPIが自動的に使われます。

たとえば、こんなエンドポイントがあります。

APIルート概要
/api/auth/signinログインページ
/api/auth/signoutログアウト処理
/api/auth/session現在のログイン状態確認
/api/auth/callback/credentialsログイン成功後にユーザー情報を処理
/api/auth/csrfログイン中のユーザーを識別するための電子的な証明書を取得
※電子的な証明書=トークン

これらを1つ1つ手動で作ると管理が大変です。

そこで、[...nextauth] というファイル1つにまとめることで、
これらすべてのAPIルートを一括で定義・管理できるようになります。

App Router で実装

Next.js 13 以降では、新しく登場した app/ ディレクトリを使う構成(App Router)が推奨されています。これが 新規プロジェクトやモダンな構成に適した形です。

App Router のファイル構成

[...nextauth] とは?Next.jsでログイン実装

App Router の実装内容

// app/api/auth/[...nextauth]/route.ts

// 認証のエントリーポイント
import NextAuth from "next-auth/next";
import { authOptions } from "@/lib/auth";

// NextAuthに設定を渡して処理を作成
const handler = NextAuth(authOptions);

// App RouterではGETとPOSTのメソッドを個別にエクスポートする必要あり
export { handler as GET, handler as POST };
// lib/auth.ts

import CredentialsProvider from "next-auth/providers/credentials";
import type { Session } from "next-auth";
import type { JWT } from "next-auth/jwt"; // NextAuth.jsが使っているトークン(認証情報)の型名
import type { NextAuthOptions } from "next-auth";

// JWTにカスタム情報(role)を追加する場合の型定義
interface Token extends JWT {
  role?: string;
}

export const authOptions: NextAuthOptions = {
  // ① ログイン方法の指定(ここではIDとパスワードによる認証)
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        username: { label: "ユーザーID", type: "text" },
        password: { label: "パスワード", type: "password" },
      },
      // 認証処理:環境変数のユーザー名・パスワードと一致すれば成功
      async authorize(credentials) {
        if (
          credentials?.username === process.env.ADMIN_USERNAME &&
          credentials?.password === process.env.ADMIN_PASSWORD
        ) {
          return { id: "1", name: "管理者", role: "admin" };
        }
        return null; // 認証失敗
      },
    }),
  ],

  // ② カスタムページ(ログイン画面など)を指定
  pages: {
    signIn: "/auth/signin", // 独自ログインページを使う場合
  },

  // ③ セッションの設定(JWT方式を利用)
  session: {
    strategy: "jwt",  // サーバーセッションではなくトークンで管理
    maxAge: 100,      // トークンの有効期限(秒)
  },

  // ④ コールバック処理(トークンやセッションに追加情報を含める)
  callbacks: {
    // JWT作成時:ユーザー情報からroleをtokenに追加
    async jwt({ token, user }: { token: Token; user?: unknown }) {
      if (user && typeof user === "object" && "role" in user) {
        token.role = (user as { role?: string }).role;
      }
      return token;
    },
    // セッション作成時:tokenからroleを取り出してsessionに追加
    async session({ session, token }: { session: Session; token: Token }) {
      session.user = {
        ...session.user,
        role: token.role ?? null,
      } as typeof session.user & { role?: string | null };
      return session;
    },
  },
};

Page Router で実装

pages/ ディレクトリを使う旧構成で、Next.js 初期から使われていたルーターです。
今でも既存プロジェクトではよく使われていますが、新規プロジェクトではあまり使われません
今後は app/ を使う App Router が推奨されています。

Pages Router のファイル構成

[...nextauth] とは?Next.jsでログイン実装

Pages Router の実装内容

// pages/api/auth/[...nextauth].ts

import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import type { Session } from "next-auth";
import type { JWT } from "next-auth/jwt";

// JWTにカスタム情報(role)を追加する場合の型定義
interface Token extends JWT {
  role?: string;
}

export default NextAuth({
  // ① ログイン方法の指定(ここではIDとパスワードによる認証)
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        username: { label: "ユーザーID", type: "text" },
        password: { label: "パスワード", type: "password" },
      },
      // 認証処理:環境変数のユーザー名・パスワードと一致すれば成功
      async authorize(credentials) {
        if (
          credentials?.username === process.env.ADMIN_USERNAME &&
          credentials?.password === process.env.ADMIN_PASSWORD
        ) {
          return { id: "1", name: "管理者", role: "admin" };
        }
        return null; // 認証失敗
      },
    }),
  ],

  // ② カスタムページ(ログイン画面など)を指定
  pages: {
    signIn: "/auth/signin", // 独自ログインページを使う場合
  },

  // ③ セッションの設定(JWT方式を利用)
  session: {
    strategy: "jwt",  // サーバーセッションではなくトークンで管理
    maxAge: 100,      // トークンの有効期限(秒)
  },

  // ④ コールバック処理(トークンやセッションに追加情報を含める)
  callbacks: {
    // JWT作成時:ユーザー情報からroleをtokenに追加
    async jwt({ token, user }: { token: Token; user?: unknown }) {
      if (user && typeof user === "object" && "role" in user) {
        token.role = (user as { role?: string }).role;
      }
      return token;
    },
    // セッション作成時:tokenからroleを取り出してsessionに追加
    async session({ session, token }: { session: Session; token: Token }) {
      session.user = {
        ...session.user,
        role: token.role ?? null,
      } as typeof session.user & { role?: string | null };
      return session;
    },
  },
});

まとめ

比較項目Pages RouterApp Router
構成1ファイル完結型設定分離型(lib/auth.ts)推奨
エクスポート方法export defaultexport { GET, POST }
推奨App Router移行前
既存プロジェクト
Next.js 13以降の新規開発

ファイル1つ(または2つ)で以下すべてのAPIが動く!そのため、それぞれを個別に作る必要なし!

  • /api/auth/signin
  • /api/auth/signout
  • /api/auth/session
  • /api/auth/callback/credentials
  • /api/auth/csrf
でじぼう
でじぼう

おつかれさまでした!

コメント