はじめに
Auth.js(NextAuth.js v4)を使って、Next.js(App Router)にGitHubとGoogleのソーシャルログインを実装してみます。
npm install next-authで入るのはv4(NextAuth.js)です。Auth.jsという名前になったv5は、2026年10月時点でもベータ版として配布されています。v5では、環境変数の接頭辞がNEXTAUTH_からAUTH_に変わるなど、設定の書き方が変わっています。この記事のコードは、Next.js 16.3.8とnext-auth 4.24.15でビルドが通ることを確認しました。
下準備
必要なパッケージをインストールする
Next.jsをインストールします。
npx create-next-app@latest next-auth-demo質問には以下のように回答します。
✔ Would you like to use the recommended Next.js defaults? › No, customize settings✔ Would you like to use TypeScript? … Yes✔ Which linter would you like to use? › ESLint✔ Would you like to use React Compiler? … Yes✔ Would you like to use Tailwind CSS? … Yes✔ Would you like your code inside a `src/` directory? … Yes✔ Would you like to use App Router? (recommended) … Yes✔ Would you like to customize the import alias (`@/*` by default)? … No作成したプロジェクトのフォルダに移動して、Auth.jsとreact-iconsをインストールします。
react-iconsはログインボタンにソーシャルアイコンを設定するためのものなので、任意で大丈夫です。
cd next-auth-demonpm install next-auth react-iconsshadcn/uiを初期化します。
npx shadcn@latest init簡易的なページ作成のためにshadcn/uiのコンポーネントを追加します。
npx shadcn@latest add button card avatar.env.localを追加します。
touch .env.local.env.localには以下のように記載しておきます。
実際にサイトを公開するときは、NEXTAUTH_URLにサイトのURLを設定してください。
NEXTAUTH_URL=http://localhost:3000NEXTAUTH_SECRET=NEXTAUTH_SECRETに設定するシークレットキーは、以下のコマンドを実行して生成した値を設定します。
NEXTAUTH_SECRETを途中で変更すると、発行済みのJWTを復号できずエラーになるので、変えないようにしてください。
openssl rand -base64 32ページを作成する
Auth.jsの設定と、認証用のAPIのルートを作成します。プロバイダにはGitHubとGoogleを設定します。
import NextAuth from "next-auth";import GitHub from "next-auth/providers/github";import Google from "next-auth/providers/google";export const authOptions = { providers: [ GitHub({ clientId: process.env.GITHUB_ID!, clientSecret: process.env.GITHUB_SECRET!, }), Google({ clientId: process.env.GOOGLE_ID!, clientSecret: process.env.GOOGLE_SECRET!, }), ],};const handler = NextAuth(authOptions);export { handler as GET, handler as POST };ログインページを作成します。ログイン後に戻るURLをcallbackUrlで受け取ります。
import LoginButtons from "@/components/LoginButtons";export default async function LoginPage({ searchParams }: { searchParams: Promise<{ callbackUrl?: string }> }) { const { callbackUrl } = await searchParams; return ( <div className="max-w-sm space-y-4"> <h1 className="text-xl font-bold">ログイン</h1> <LoginButtons callbackUrl={callbackUrl ?? "/"} /> </div> );}マイページを作成します。ログインしていない場合は、ログインページにリダイレクトします。
import { authOptions } from "@/app/api/auth/[...nextauth]/route";import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";import { getServerSession } from "next-auth";import { redirect } from "next/navigation";export default async function MyPage() { const session = await getServerSession(authOptions); if (!session) { redirect("/login?callbackUrl=%2Fmypage"); } const user = session.user; return ( <div className="space-y-4"> <h1 className="text-xl font-bold">マイページ</h1> <Card> <CardHeader> <CardTitle>アカウント情報</CardTitle> </CardHeader> <CardContent className="flex items-center gap-4"> <Avatar> <AvatarImage src={user?.image ?? ""} alt={user?.name ?? ""} /> <AvatarFallback>{(user?.name ?? user?.email ?? "U").slice(0, 1).toUpperCase()}</AvatarFallback> </Avatar> <div className="space-y-1"> <p className="font-medium">{user?.name ?? "(名前なし)"}</p> <p className="text-sm text-muted-foreground">{user?.email ?? "(メールなし)"}</p> </div> </CardContent> </Card> </div> );}レイアウトのヘッダーに、ログインの状態に応じたリンクを表示します。
import { authOptions } from "@/app/api/auth/[...nextauth]/route";import LogoutButton from "@/components/LogoutButton";import { getServerSession } from "next-auth";import Link from "next/link";import "./globals.css";export default async function RootLayout({ children }: { children: React.ReactNode }) { const session = await getServerSession(authOptions); return ( <html lang="ja"> <body className="min-h-dvh"> <header className="border-b"> <div className="mx-auto flex max-w-4xl items-center justify-between gap-4 p-4"> <Link href="/" className="font-bold"> Auth Test </Link> <nav className="flex items-center gap-3 text-sm"> <Link href="/" className="underline"> Top </Link> {session ? ( <> <Link href="/mypage" className="underline"> MyPage </Link> <LogoutButton /> </> ) : ( <> <Link href="/login" className="underline"> Login </Link> <Link href="/mypage" className="underline"> MyPage </Link> </> )} </nav> </div> </header> <main className="mx-auto max-w-4xl p-6">{children}</main> </body> </html> );}トップページを作成します。
import { authOptions } from "@/app/api/auth/[...nextauth]/route";import { getServerSession } from "next-auth";import Link from "next/link";export default async function Home() { const session = await getServerSession(authOptions); return ( <div className="space-y-4"> <h1 className="text-xl font-bold">Top</h1> {session ? ( <Link href="/mypage" className="underline"> マイページへ </Link> ) : ( <Link href="/login" className="underline"> ログインへ </Link> )} </div> );}ログインボタンとログアウトボタンは、クライアントコンポーネントとして作成します。
"use client";import { Button } from "@/components/ui/button";import { signIn } from "next-auth/react";import { FaGithub } from "react-icons/fa";import { FcGoogle } from "react-icons/fc";type Props = { callbackUrl: string;};export default function LoginButtons({ callbackUrl }: Props) { return ( <div className="space-y-2"> <Button variant={"outline"} className="w-full" onClick={() => signIn("github", { callbackUrl })}> <FaGithub /> GitHubでログイン </Button> <Button variant={"outline"} className="w-full" onClick={() => signIn("google", { callbackUrl })}> <FcGoogle /> Googleでログイン </Button> </div> );}"use client";import { signOut } from "next-auth/react";export default function LogoutButton() { return ( <button type="button" className="underline bg-transparent p-0 text-sm" onClick={() => signOut({ callbackUrl: "/" })}> ログアウト </button> );}各プロバイダの設定
GitHub
- GitHubのSettingsを開きます。
- メニューの一番下にあるDeveloper settingsを開きます。
- メニューのOAuth Appsを開きます。
- New OAuth Appを選択します。
- 下の表を参考に各項目を設定してください。
- Register applicationを選択します。
- Generate a new client secretをクリックし、シークレットキーを発行します。
設定する項目は以下のとおりです。ローカルで作成する際の例なので、公開するサイトの場合は実際のドメインに変更してください。
Application name | 任意のアプリ名 |
|---|---|
Homepage URL | http://localhost:3000 |
Authorization callback URL | http://localhost:3000/api/auth/callback/github |
Client IDとClient secretsが表示されるので、コピーして.env.localに設定してください。
GITHUB_ID=Ov23xxxxxxxxxxxxxxxxGITHUB_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx- Google Cloudにアクセスして、新しいプロジェクトを作成します。
- ダッシュボードの「APIとサービス > 認証情報」を開きます。
- 「認証情報を作成 > OAuth クライアント ID」を選択します。新しいプロジェクトでは、先にOAuth同意画面の設定を求められるので、画面の案内に沿ってアプリ名などを設定します。
- 「アプリケーションの種類」を「ウェブ アプリケーション」にし、「名前」に任意の名前を設定します。
- 「承認済みの JavaScript 生成元」にはパスなしのURL、「承認済みのリダイレクト URI」にはAPIのURIを設定します(下の表)。
- 「作成」を選択します。
設定する項目は以下のとおりです。ローカルで作成する際の例なので、公開するサイトの場合は実際のドメインに変更してください。
承認済みの JavaScript 生成元 | http://localhost:3000 |
|---|---|
承認済みのリダイレクト URI | http://localhost:3000/api/auth/callback/google |
クライアント IDとクライアント シークレットが表示されるので、コピーして.env.localに設定してください。
GOOGLE_ID=123456789012-xxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.comGOOGLE_SECRET=GOCSPX-xxxxxxxxxxxxxxxxxxxxxxxxClient secretやクライアント シークレット、NEXTAUTH_SECRETは、Gitのリポジトリにコミットしたり、公開の場所に書いたりしないでください。漏れた場合は、各サービスの画面で作り直します。
参考・引用
- Getting Started | NextAuth.js(新しいタブで開く)
- Options | NextAuth.js(新しいタブで開く)
- Migrating to v5 | Auth.js(新しいタブで開く)
- OAuth アプリの作成 - GitHubドキュメント(新しいタブで開く)