next-auth の使い方

Authentication for Next.js

v4.24.133.2M/週ISC認証
AI生成コンテンツ

この記事はAIによって生成されました。内容の正確性は保証されません。最新の情報は公式ドキュメントをご確認ください。

next-auth の使い方 — Next.js に認証機能を最速で導入する方法

一言でいうと

next-auth は、Next.js アプリケーションに OAuth・メール認証・JWT ベースの認証を簡単に組み込める、フルスタック認証ライブラリです。Google や GitHub などの主要プロバイダーに対応し、数十行のコードで本格的な認証基盤を構築できます。

注意: この記事は next-auth v4 系(4.24.x)を対象としています。v5(Auth.js)では API が大幅に変更されているため、バージョンにご注意ください。

どんな時に使う?

  1. Next.js アプリに Google / GitHub / Apple などのソーシャルログインを導入したい時 — プロバイダー設定を数行書くだけで OAuth フローが完成します
  2. JWT またはデータベースセッションによるユーザー管理を手軽に実装したい時 — セッション管理、CSRF 対策、Cookie ポリシーがデフォルトで安全に設定されています
  3. メールリンク(パスワードレス)認証を実装したい時 — Email プロバイダーを使えば、マジックリンク方式の認証を簡単に構築できます

インストール

# npm
npm install next-auth

# yarn
yarn add next-auth

# pnpm
pnpm add next-auth

基本的な使い方(next-auth セットアップ)

1. API ルートの作成

// pages/api/auth/[...nextauth].ts
import NextAuth, { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import GitHubProvider from "next-auth/providers/github";

export const authOptions: NextAuthOptions = {
  secret: process.env.NEXTAUTH_SECRET,
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
    GitHubProvider({
      clientId: process.env.GITHUB_ID!,
      clientSecret: process.env.GITHUB_SECRET!,
    }),
  ],
};

export default NextAuth(authOptions);

2. 環境変数の設定

# .env.local
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-random-secret-string  # openssl rand -base64 32 で生成推奨

GOOGLE_CLIENT_ID=xxx
GOOGLE_CLIENT_SECRET=xxx
GITHUB_ID=xxx
GITHUB_SECRET=xxx

3. SessionProvider でアプリ全体をラップ

// pages/_app.tsx
import { SessionProvider } from "next-auth/react";
import type { AppProps } from "next/app";

export default function App({
  Component,
  pageProps: { session, ...pageProps },
}: AppProps) {
  return (
    <SessionProvider session={session}>
      <Component {...pageProps} />
    </SessionProvider>
  );
}

4. コンポーネントでセッションを利用

// components/AuthButton.tsx
import { useSession, signIn, signOut } from "next-auth/react";

export default function AuthButton() {
  const { data: session, status } = useSession();

  if (status === "loading") return <p>読み込み中...</p>;

  if (session) {
    return (
      <div>
        <p>ログイン中: {session.user?.email}</p>
        <button onClick={() => signOut()}>ログアウト</button>
      </div>
    );
  }

  return <button onClick={() => signIn()}>ログイン</button>;
}

よく使う API — next-auth の主要機能

1. useSession() — クライアント側でセッション取得

最も頻繁に使うフックです。status"loading" | "authenticated" | "unauthenticated" の 3 値を返します。

import { useSession } from "next-auth/react";

function Dashboard() {
  const { data: session, status } = useSession({
    required: true, // 未認証時は自動でサインインページへリダイレクト
    onUnauthenticated() {
      // required: true の場合のカスタムハンドラ(任意)
      console.log("認証が必要です");
    },
  });

  if (status === "loading") return <p>読み込み中...</p>;

  return <p>ようこそ、{session!.user?.name} さん</p>;
}

2. getServerSession() — サーバー側でセッション取得

API ルートや getServerSideProps でセッションを安全に取得します。getSession() よりも推奨されます(余分な HTTP リクエストが発生しないため)。

// pages/api/protected.ts
import type { NextApiRequest, NextApiResponse } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "./auth/[...nextauth]";

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  const session = await getServerSession(req, res, authOptions);

  if (!session) {
    return res.status(401).json({ error: "認証が必要です" });
  }

  return res.json({
    message: `こんにちは、${session.user?.name} さん`,
  });
}
// pages/dashboard.tsx — getServerSideProps での利用
import type { GetServerSidePropsContext } from "next";
import { getServerSession } from "next-auth/next";
import { authOptions } from "./api/auth/[...nextauth]";

export async function getServerSideProps(context: GetServerSidePropsContext) {
  const session = await getServerSession(context.req, context.res, authOptions);

  if (!session) {
    return { redirect: { destination: "/api/auth/signin", permanent: false } };
  }

  return { props: { session } };
}

3. signIn() / signOut() — 認証フローの制御

import { signIn, signOut } from "next-auth/react";

// 特定のプロバイダーを指定してサインイン
function LoginButtons() {
  return (
    <div>
      {/* Google でサインイン */}
      <button onClick={() => signIn("google")}>Google でログイン</button>

      {/* GitHub でサインイン(コールバックURL指定) */}
      <button onClick={() => signIn("github", { callbackUrl: "/dashboard" })}>
        GitHub でログイン
      </button>

      {/* Credentials プロバイダーでサインイン(リダイレクトなし) */}
      <button
        onClick={async () => {
          const result = await signIn("credentials", {
            redirect: false,
            email: "user@example.com",
            password: "password123",
          });
          if (result?.error) {
            console.error("ログイン失敗:", result.error);
          }
        }}
      >
        メールでログイン
      </button>

      {/* サインアウト */}
      <button onClick={() => signOut({ callbackUrl: "/" })}>ログアウト</button>
    </div>
  );
}

4. Callbacks — セッション・JWT のカスタマイズ

callbacks を使うと、セッションオブジェクトに独自のフィールドを追加できます。

// pages/api/auth/[...nextauth].ts
import NextAuth, { NextAuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";

export const authOptions: NextAuthOptions = {
  secret: process.env.NEXTAUTH_SECRET,
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
  ],
  callbacks: {
    async jwt({ token, account, profile }) {
      // 初回サインイン時に追加情報を token に格納
      if (account) {
        token.accessToken = account.access_token;
        token.id = token.sub;
      }
      return token;
    },
    async session({ session, token }) {
      // クライアントに公開する session オブジェクトをカスタマイズ
      session.accessToken = token.accessToken as string;
      session.user.id = token.id as string;
      return session;
    },
    async signIn({ user, account, profile }) {
      // 特定ドメインのメールのみ許可する例
      const email = user.email ?? "";
      if (email.endsWith("@yourcompany.com")) {
        return true;
      }
      return false; // false を返すとサインイン拒否
    },
  },
};

export default NextAuth(authOptions);

型を拡張する場合は、以下のように宣言マージを行います。

// types/next-auth.d.ts
import "next-auth";

declare module "next-auth" {
  interface Session {
    accessToken: string;
    user: {
      id: string;
      name?: string | null;
      email?: string | null;
      image?: string | null;
    };
  }
}

declare module "next-auth/jwt" {
  interface JWT {
    accessToken?: string;
    id?: string;
  }
}

5. Credentials Provider — ID/パスワード認証

独自のユーザーデータベースと組み合わせた認証を実装できます。

// pages/api/auth/[...nextauth].ts
import NextAuth, { NextAuthOptions } from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

export const authOptions: NextAuthOptions = {
  secret: process.env.NEXTAUTH_SECRET,
  session: {
    strategy: "jwt", // Credentials 利用時は JWT 必須
  },
  providers: [
    CredentialsProvider({
      name: "メールアドレス",
      credentials: {
        email: { label: "メール", type: "email", placeholder: "user@example.com" },
        password: { label: "パスワード", type: "password" },
      },
      async authorize(credentials) {
        // ここで DB 問い合わせやパスワード検証を行う
        const user = await findUserByEmail(credentials?.email ?? "");
        if (user && await verifyPassword(credentials?.password ?? "", user.hashedPassword)) {
          return { id: user.id, name: user.name, email: user.email };
        }
        return null; // null を返すとサインイン失敗
      },
    }),
  ],
  pages: {
    signIn: "/auth/signin", // カスタムサインインページ
    error: "/auth/error",
  },
};

export default NextAuth(authOptions);

類似パッケージとの比較

特徴next-auth (v4)Auth.js (v5)clerklucia
対応フレームワークNext.js 専用Next.js, SvelteKit, Express 等Next.js, React, Remix 等フレームワーク非依存
ホスティングセルフホストセルフホストSaaS(マネージド)セルフホスト
OAuth プロバイダー数60+80+20+自前実装
DB セッションN/A(SaaS管理)
JWT セッションN/A❌(DB のみ)
Credentials 認証✅(制限あり)✅(制限あり)
料金無料無料フリーミアム無料
App Router 対応部分的ネイティブ対応
学習コスト低〜中中〜高

補足: next-auth v4 の後継が Auth.js (v5) です。新規プロジェクトで App Router を使う場合は v5 への移行を検討してください。ただし v4 は依然として広く使われており、安定しています。

注意点・Tips

1. NEXTAUTH_SECRET は必ず設定する

本番環境では NEXTAUTH_SECRET が未設定だとエラーになります。以下のコマンドで安全なシークレットを生成してください。

openssl rand -base64 32

2. getServerSession を優先的に使う

クライアント側の getSession() はサーバーに HTTP リクエストを送信してセッションを取得します。サーバーサイド(API ルート、getServerSideProps)では getServerSession() を使うことで、不要なネットワークラウンドトリップを回避できます。

3. Credentials Provider の制限を理解する

Credentials Provider を使う場合、データベースセッション(strategy: "database")は利用できません。JWT 戦略のみ対応です。また、useSession()updaterefetchInterval によるセッション更新は JWT の有効期限に依存するため、リアルタイムなユーザー情報の反映には工夫が必要です。

4. Middleware でルート保護する

Next.js の Middleware と組み合わせることで、ページ単位の認証チェックを一元管理できます。

// middleware.ts
export { default } from "next-auth/middleware";

export const config = {
  matcher: ["/dashboard/:path*", "/settings/:path*"],
};

より細かい制御が必要な場合:

// middleware.ts
import { withAuth } from "next-auth/middleware";

export default withAuth(
  function middleware(req) {
    // 認証済みユーザーのみここに到達
    console.log("token:", req.nextauth.token);
  },
  {
    callbacks: {
      authorized: ({ token }) => token?.role === "admin",
    },
  }
);

export const

比較記事