🙆‍♀️

【ハンズオン】Auth.jsを使ってNext.jsアプリケーションの認証機能を爆速で実装しよう

に公開

背景

こんにちは。もんたです。

最近会社でNext.jsを使ったアプリケーションの開発をゼロから任せていただいているのですが、そこで認証機能の実装にAuth.jsを使ってみて感動したので共有です。

結論としてはAuth.jsはかなりおすすめです!

この記事では、Auth.jsを使った基本的な実装ができるようになるまで解説しております。
Auth.jsが気になっている方はぜひご覧ください!


この記事を読むことで、以下のことが理解できます!

  1. Auth.jsとは何か
  2. Auth.jsを導入するまでの流れ
  3. Auth.jsでGoogle認証をする方法

Auth.jsとは

まずはGemini2.5 Proくんが作ってくれたわかりやすい説明をご覧ください。

僕よりも数倍わかりやすく解説してくれています。

🤖 Auth.jsとは

Auth.jsってなに? 🤔 超ざっくり解説!

Auth.js (オース・ジェイエス) は、Next.jsなどのウェブフレームワークで作るアプリに 「ログイン機能 (認証)」をめちゃくちゃ簡単に追加できるツール のことです!✨

例えるなら、アプリの入り口に立ってくれる 万能なドアマン🔑 みたいなイメージはそのままです。

<center>🚪 アプリ + 頼れるドアマン (Auth.js) = 安心!</center>

このAuth.jsは、OSS (オープンソースソフトウェア) なので、誰でも無料で使えますし、世界中の開発者が協力して開発・改善を進めています 🌍🤝

元々は 「NextAuth.js」 という名前で、Next.js向けに作られて大人気になりましたが、「もっと色々なフレームワークでこの便利さを使いたい!」 という声に応えて、Auth.jsとして生まれ変わったんです!


Auth.jsを使うと何が嬉しいの? ✨ (メリット)

この進化したドアマン (Auth.js) を使うと、こんな良いことがあります!

  • とにかく楽ちん!🚀: ログイン機能の自作は大変…💦 でもAuth.jsを使えば、驚くほど少ないコードで、早く簡単に 実装できます! 開発時間を大幅に節約!
  • 色々なログイン方法に標準対応!🤝:
    • Google / GitHub / X (Twitter) などのSNSアカウントログイン (OAuth認証)
    • メールアドレス📧とパスワード🔑でのログイン
    • メールでのリンク認証 (パスワード不要!)
      など、主要な認証方法がたくさん用意されています。選んで設定するだけ!
  • セキュリティもおまかせ!🛡️: 認証のセキュリティ対策は重要ですが複雑。Auth.jsは、面倒で重要なセキュリティのベストプラクティスを組み込んでくれているので、より安全な実装がしやすくなります。
  • 多くのフレームワークに対応!🏗️: Next.jsはもちろん、SvelteKitやExpress、SolidStartなど、様々なフレームワークや環境で利用できるように設計されています。(対応状況は拡大中です!)
  • コミュニティが活発!💬: 元々のNextAuth.jsからの流れもあり、多くの開発者が利用しているので、情報交換や問題解決がしやすい環境です。

逆に、ちょっと注意な点は? 🤔 (デメリット/注意点)

もちろん、万能ではありません。知っておきたい点も。

  • 少しお勉強が必要✏️: 初めて使う際は、Auth.js特有の設定方法(プロバイダー、コールバックなど)や、お使いのフレームワークとの連携方法を少し学ぶ必要があります。
  • 超特殊な要件には限界も?⚙️: 非常にユニークで複雑な認証フローが必要な場合、Auth.jsの標準機能だけでは足りず、自分で追加のコードを書く必要が出てくるかもしれません。
  • ライブラリへの依存と追従🔄: Auth.jsも進化していくので、バージョンアップに合わせて自分のアプリも更新していく作業は必要になります。(これは多くの外部ライブラリで共通ですね!)

どんな機能があるの? (基本をサクッと紹介!)

Auth.jsを構成する主な部品(機能)はこんな感じです。

  • コア (Core) 🧠:
    • Auth.jsの中心的な機能。どのフレームワークでも共通して使われる認証処理の基本ロジックを提供します。
  • フレームワーク連携 (Framework Adapters) 🔗:
    • Next.js (App Router/Pages Router), SvelteKit, Expressなど、特定のフレームワークでAuth.jsを簡単に使えるようにするための接続部品です。
  • プロバイダー (Providers) 🔌:
    • Google, GitHub, Apple, メール/パスワード (Credentials) など、具体的な「ログイン方法」を提供する部品群です。使いたいものを設定ファイルに追加します。
  • アダプター (Adapters) ↔️:
    • ユーザー情報やセッション情報をデータベース(PostgreSQL, MySQL, MongoDBなど)に保存したい場合に使う接続部品。PrismaなどのORM用アダプターも豊富です。
  • コールバック (Callbacks) 📞:
    • 認証フローの特定のタイミング(例: ログイン成功直後、セッション読み込み時)で、独自の処理を差し込むためのフックポイントです。ここでユーザー情報のカスタマイズなどができます。

まとめ ✨

  • Auth.jsは、Next.jsなどのモダンなウェブフレームワークに、認証機能を簡単・安全に追加できる、超便利なOSSツール
  • 元々はNextAuth.jsとして始まり、より多くの環境で使えるように進化した!
  • メリットは、開発効率UP、多様な認証方法、セキュリティ向上、複数フレームワーク対応など!
  • デメリットは、多少の学習コストや、超特殊要件への対応限界など。

ウェブアプリにログイン機能が必要になったら、Auth.jsは最初に検討すべき強力な選択肢と言えるでしょう! 😊

はい。ざっくりとAuth.jsで何ができるかわかってもらえたかと思います。

では、最後までお読みいただき、ありがとうございました。


っていうのは冗談です。

ちゃんとAuth.jsについてできるだけわかりやすく解説していきます。

Auth.jsとは

はい。AIの解説にもあったように、Auth.jsはOSSなので、無料で誰でも使えます。

ソースはこちら。

https://github.com/nextauthjs/next-auth

Auth.js は、あらゆるプラットフォームのあらゆるフレームワークで、あらゆる JS ランタイムを使用して最新のアプリケーションを認証するための標準 Web API 上に構築されたオープンソース パッケージのセットです。(Google翻訳)

リポジトリにもありますがAuth.jsは「柔軟で使いやすい」「デフォルトで安全」「TSに対応しているので型安全」といった特徴があります。


個人的にAuth.jsを使った実装をしていいなと思ったのはやはり、「デフォルトで安全」の箇所にあるとおり、<font color="red">「面倒臭いけどやらないといけないセキュリティ対策」の多くをデフォルトで、かつベストプラクティスに従った形で提供している</font>部分になります。


例えば、独自にログイン機能を実装するとなると以下のようなことをしないといけません。

  • CSRF対策(CSRFトークンの生成、埋め込みなど)
  • 安全なセッション管理
    • 十分な長さのセッションIDの生成
    • Cookieに属性を設定する
    • 適切なセッション有効期間の設定
    • ログアウト時にサーバー側セッションを破棄する

などがあります。

なんとAuth.jsは以下を肩代わりにしてくれます。

  • CSRF対策(主要なエンドポイントでCSRFトークンの生成・検証を自動で行ってくれる)
  • 安全なセッション管理
    • 安全なセッションID、または暗号化(JWT)を自動生成してくれる
    • 推奨される安全なCookie属性をデフォルトで適用
    • セッション有効期間の設定や管理機能の提供
    • ログアウト処理でセッションやトークンを適切に無効化
  • Google認証などのプロバイダー設定をめちゃくちゃ簡単に実装


自分は独自でGoogle認証を実装したことがあったのですが、その時はめちゃくちゃ実装が面倒だった記憶があります。
しかし、Auth.jsだとちゃっとやってぽっとやってぺっとやればできたのは感動しました。

Auth.jsがサポートしている認証方法

こちらにサポートしているプロバイダーがまとめられています。

https://authjs.dev/reference/core/providers

主要なところでいうと以下の通りでしょうか。

プロバイダー名/種別 概要 URL
Google Googleアカウントでログインできます。最も一般的に利用されるプロバイダーの1つです。 https://authjs.dev/reference/core/providers/google
GitHub GitHubアカウントでログインできます。開発者向けサービスでよく利用されます。 https://authjs.dev/reference/core/providers/github
Apple Apple IDでログインできます。iOSアプリ連携などで利用されます。 https://authjs.dev/reference/core/providers/apple
Facebook Facebookアカウントでログインできます。 https://authjs.dev/reference/core/providers/facebook
X (旧Twitter) Xアカウントでログインできます。(※APIの利用ポリシー変更に注意が必要です) https://authjs.dev/reference/core/providers/twitter
LINE LINEアカウントでログインできます。日本国内で人気のプロバイダーです。 https://authjs.dev/reference/core/providers/line
Azure Active Directory (Azure AD / Microsoft Entra ID) Microsoftの職場/学校アカウント (Entra ID) や個人アカウント (Microsoft Account) でログインできます。 https://authjs.dev/reference/core/providers/azure-ad
その他多数のOAuth/OIDCプロバイダー (Discord, Slack, Spotify, GitLab, Zoom etc.) 数十種類以上の一般的なWebサービスやプラットフォームのアカウントを利用したログインに対応しています。
Email Provider (パスワードレス) ユーザーのメールアドレス宛に特別なログインリンク(マジックリンク)を送信し、クリックすることで認証します。パスワード管理が不要。(※DBアダプター必要) https://authjs.dev/reference/core/providers/email
Credentials Provider (カスタム認証) メールアドレス/パスワードなど、開発者が定義した任意の認証情報と独自の検証ロジックで認証機能を実装できます。 https://authjs.dev/reference/core/providers/credentials

【ハンズオン】Auth.jsの導入するまでの流れ

自分はAuth.jsを用いた認証を実装するにあたって以下の動画を参考にしました。

https://www.youtube.com/watch?v=xpJ4VBc5Qr0

めちゃくちゃわかりやすく解説されているのでおすすめです!
この動画ではGitHubを用いた場合の実装方法なんかもあるので、GitHubを使った認証を実装したいと考えている人はぜひご覧ください!


こちらのドキュメントに従ってAuth.jsの導入を始めていきます。

step1:Auth.jsのインストール

npm install next-auth@beta

step2:セットアップ

npx auth secret

envファイルにAUTH_SECRETという環境変数を設定します。

Next.jsを使っている場合、上記のスクリプトを実行するとenvファイルに自動で以下の環境変数が追加されます。(Next.jsを使っている場合)

AUTH_SECRET="********"

step3:設定

auth.tsという名前のファイルをプロジェクト内に作成し、以下のコードを追加します。

auth.ts
import NextAuth from "next-auth"
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [],
})

続いて、/app/api/auth/[...nextauth]/route.tsにハンドラーを追加します。

route.ts
import { handlers } from "@/auth" // Referring to the auth.ts we just created
export const { GET, POST } = handlers

最後に、middleware.tsを作成し、以下のコードを追加する。

middleware.ts
export { auth as middleware } from "@/auth"

ここでやっていることは、Auth.jsを使う上での最低限の設定のようなものです。

ここでやっていること

この手順は、Auth.jsをNext.jsアプリ (App Router) で動かすための「最低限の準備」のようなものです。それぞれのファイルが連携して、認証機能の土台を作っています。


1. auth.ts の作成:Auth.jsの司令塔!⚙️

auth.ts
import NextAuth from "next-auth"

// ここでAuth.jsの基本的な設定を行う!
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [], // ← 今は空だけど、ここに使う認証方法(Googleとか)を追加していく
})
  • 役割: このファイルは、あなたのアプリにおける Auth.jsの設定の中心、「司令塔」 のようなものです。
  • NextAuth({...}): これがAuth.jsの本体を呼び出して設定する部分です。{...} の中に、どんな認証方法(プロバイダー)を使うか、認証後の動きをどうするか、などの細かいルールを書いていきます。(今はまだ providers: [] と空っぽですが、後でGoogleやGitHubなどの設定をここに追加します。)
  • export const { ... } = NextAuth(...): NextAuth 関数は、設定を受け取って、Auth.jsを動かすために必要な便利な道具一式を返してくれます。それを export することで、他のファイルから使えるようにしています。
    • handlers: 認証関連の通信(「ログイン処理して!」「ログアウト処理して!」など)を受け付ける担当者。後述の route.ts で使います。
    • signIn, signOut: それぞれ「ログイン開始!」「ログアウト!」の合図を送るための関数。ボタンクリック時などに呼び出します。
    • auth: 「今ログインしてるユーザーは誰?」とサーバー側(APIやページ表示前)で確認するための関数。後述の middleware.ts などで使います。
  • ファイル名: auth.ts という名前が一般的ですが、🐶コメントにあるように、実は他の名前(例: auth.config.ts)でも大丈夫です。

一言でいうと: auth.tsAuth.jsの基本的な設定を行い、認証に必要な主要な機能(道具)を取り出すファイル です。


2. /app/api/auth/[...nextauth]/route.ts の作成:認証の総合受付窓口🚪

route.ts
// さっき auth.ts で用意した「通信担当者」をインポート
import { handlers } from "@/auth"

// GETリクエストもPOSTリクエストも、その担当者にお任せ!
export const { GET, POST } = handlers
  • 役割: このファイルは、Next.jsの APIルート と呼ばれるもので、Auth.jsに関連する 全ての通信(リクエスト)を受け付ける「総合受付窓口」 のような役割を果たします。
  • /api/auth/[...nextauth]: この特別なファイルパスのおかげで、例えば /api/auth/signin/google/api/auth/callback/github/api/auth/signout といった、Auth.jsが必要とする様々なURLへのアクセスを一手に引き受けてくれます
  • import { handlers } ... export { GET, POST } = handlers: やっていることはシンプルで、「auth.ts で用意した通信担当者 (handlers) に、GETリクエストが来てもPOSTリクエストが来ても、全部お任せします!」と宣言しています。
  • これにより、Auth.jsは裏側で「/api/auth/signin/google にアクセスが来たら、Googleのログイン処理を開始しよう」といった判断と処理を自動で行えるようになります。

一言でいうと: このファイルは Auth.jsの認証処理に必要なAPI通信を全て受け付け、実際の処理を auth.ts に繋ぐための窓口 です。


3. middleware.ts の作成:アプリの門番👮‍♀️

middleware.ts
// auth.ts で用意した「ログイン状態チェック係」をインポートして、
// そのまま middleware として設定!
export { auth as middleware } from "@/auth"

// 通常は、どのページでこの門番を動かすか設定(config)も書くことが多い
// export const config = { matcher: ["/dashboard/:path*"] } // 例: /dashboard以下のページ
  • 役割: middleware.ts は、Next.jsアプリの ページの表示やAPIが実行される「前」に動く特別なプログラム です。まさに アプリの入り口に立つ「門番」 のような役割を果たします。
  • export { auth as middleware } ...: ここでは、auth.ts で用意した 「ログイン状態チェック係 (auth)」 を、そのまま門番 (middleware) として任命 しています。
  • 何をしてくれるか: これを設定しておくと、Auth.jsは各ページへのアクセスがあるたびに、「この人はログインしてるかな?」と自動でチェック してくれます。
    • もしログインしていなければ、自動的にログインページに飛ばす(リダイレクトする)といった動作を設定できます。(この基本的な設定だけでも、未認証ユーザーはデフォルトでログインページにリダイレクトされるようになります)
    • export const config = { matcher: [...] } を追加することで、「どのページ(パス)でこの門番にチェックしてほしいか」を指定するのが一般的です。(例: ユーザー専用のダッシュボードページなど)

一言でいうと: middleware.tsAuth.jsの認証チェック機能を使って、アプリの特定ページへのアクセスを制御する(保護する)ための門番 です。


まとめ:

この3つのステップは、

  1. Auth.jsの設定と機能を用意し (auth.ts)、
  2. 認証に関する通信の受付窓口を作り (route.ts)、
  3. ページアクセスの門番(アクセス制御)を設定する (middleware.ts)

という、Auth.jsを動かすための基本的な骨組みを作っているんですね! これで最低限の準備が整い、あとはプロバイダーを追加したり、ログイン/ログアウトボタンを作ったりしていくことになります。

Auth.jsでめちゃくちゃ重要なのがauth.tsです。
auth.tsは、Auth.jsの司令塔のような役割を担っています。

NextAuth({})という箇所がありますが、ここでAuth.jsの本体を呼び出しその中で、以下のような設定を行います。

  • どの認証方法(プロバイダー)を用いるか
  • リダイレクトはどうするか
  • 認証方法はどうするか
  • サインインのロジックはどうするか
  • ログイン後はどのページに遷移するか

といった細かな設定を行なっていきます。


ここで細かな設定を行なったのちに、handlers, signIn, signOut,authといった道具をexportすることで楽に呼び出せるようになるのです。

handlers

handlersの正体は{ GET , POST }という形式のオブジェクトです。

Auth.jsでは、認証機能をAPIで処理するために、GET, POSTのhandlerをエクスポートしています。

/api/auth/[...nextauth]/route.tsにてGET, POSTオブジェクトをエクスポートすることで、/api/auth/以下の処理は全てAuth.jsが行うようにすることができるのです。


例えば以下のような処理をAuth.jsは自動で行なってくれます。

  • /api/auth/signin(サインイン関連のGET,POST処理)
  • /api/auth/callback(コールバック関連のGET,POST処理)
  • /api/auth/signout(サインアウト周りのPOST処理)
  • /api/auth/session(セッション情報周りのGET処理)

などなど、認証周りの処理をAuth.jsにお願いするために/api/auth/[...nextauth]/route.ts{ GET , POST }オブジェクトを以下のようにエクスポートしているのです。

route.ts
import { handlers } from "@/auth" // Referring to the auth.ts we just created
export const { GET, POST } = handlers

signIn関数

signInはAuth.jsのサインイン周りの処理を担当します。

signIn関数を呼び出すことで、認証プロセスを開始することができます。

詳しい設定方法は後述しますが、以下のようにsignIn("PROVIDER_NAME")とすることで、NextAuth({})内で定義したプロバイダーを用いた認証を実行することができます。

  <form
    action={async () => {
      'use server';
      await signIn('google');
    }}
  >
    <button type="submit">
      <p>Googleでログインする</p>
    </button>
  </form>

signOut関数

signOutはAuth.jsのサインアウト周りの処理を担当します。

こちらの関数も呼び出すだけでサインアウト処理を自動で行ってくれます。
以下の処理を行なってくれます。

  1. 現在のセッションを無効化する
  2. 関連するCookieを削除する

といった処理を行ってくれて、ユーザーはログイン情報を削除することができるのです。便利ですね。

こちらも同様に関数を呼び出すだけで、ログアウト処理を行ってくれるので、開発者は認証周りを機にすることなく開発をすることができます。

auth関数

authは現在のリクエストにおける認証状況を確認する関数になります。

例えば、ログインしているユーザーの認証情報(名前、メールアドレス、IDなど)が格納されたセッションオブジェクトを取得することができます。

例えばですが、以下のようなオブジェクトがauth関数を実行することで得られます。

{
  user: {
    name: '***',
    email: '***',
    image: '***'
  },
  expires: '***'
}

これは多くのプロバイダーが提供する基本的なユーザー情報になっています。

ちなみに、以下のようにsessionをカスタマイズすることで独自で定義した認証オブジェクトを作成することができます。

auth.ts
declare module 'next-auth' {
  interface Session {
    user?: {
      test: string;
    } & DefaultSession['user'];
  }

  interface Jwt {
    test: string;
  }
}

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    // ***
  ],

  session: {
    strategy: 'jwt', // default
  },

  callbacks: {
    jwt: async ({ token }) => {
      token.test = 'test_string';
      return token
    },
    session: async ({ session, token }) => {
      session.user.test = 'test_string';
      // 以下のようにtokenからtestを参照したい場合はjwt()のカスタマイズが必須
      // session.user.test = token.test;
      return session;
    },
  },
});
{
  user: {
    name: '***',
    email: '***',
    image: '***',
    test: 'test_string' // 独自に定義できる
  },
  expires: '***'
}

【ハンズオン】Auth.jsでGoogle認証を実装してみよう

前提

Google認証を行うには以下の環境変数が必要です。

AUTH_GOOGLE_ID="***.apps.googleusercontent.com"
AUTH_GOOGLE_SECRET="***"

これらの環境変数の取得方法や設定についてはここでは取り扱わないことにします。

詳しくは以下の動画や記事がおすすめです。

https://youtu.be/xpJ4VBc5Qr0?si=nJ19eeG0lI8hIPiY&t=763

https://authjs.dev/getting-started/authentication/oauth

https://ma-vericks.com/blog/next-auth-js/

https://zenn.dev/shinryuzz/articles/f7f8f7be7842c3#google-プロバイダの追加

step1:プロバイダーのセットアップ

めちゃくちゃ簡単です。

先ほど設定したNextAuth({})providersにAuth.jsからインポートしたGoogleを代入します。

auth.ts
import NextAuth from "next-auth"
import Google from "next-auth/providers/google"
 
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [Google],

  callbacks: {
    authorized: async ({ auth }) => {
      // Logged in users are authenticated, otherwise redirect to login page
      return !!auth;
    },
  },
},
})

tesp2:middlewareでの設定

middleware.tsにて以下の設定を追加してください。

この設定が抜けると、cssが適用されずただのHTMLだけが表示されてしまいます。

middleware.ts
export const config = {
  matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
}

step3:サインインボタンの実装

続いて、ログインボタンにsignIn("google")を設定します。


import { signIn } from "@/auth"
 
export default function SignIn() {
  return (
    <form
      action={async () => {
        "use server"
        await signIn("google")
      }}
    >
      <button type="submit">Signin with Google</button>
    </form>
  )
} 

これだけで完了です。

あとはサインインボタンをクリックしたらGoogle認証の画面にリダイレクトし、Auth.jsがよしなに認証周りの処理を行ってくれます。

基本的なGoogle認証はこれだけで可能です。

もちろん、特定のドメインのアカウントだけログインさせたいみたいなこともあると思います。
そういった場合は、以下のように設定することで特定のドメインのアカウントだけログインさせることも可能です。

auth.ts
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Google({
      authorization: {
        params: {
          hd: 'mycompany.com',
        },
      },
    }),
  ],

  callbacks: {
    signIn: async ({ account, profile }) => {
      // google経由のログインかどうか
      if (account?.provider === 'google') {
        // ここでログイン日時の更新や新規ユーザーであればDBに追加するなどの処理を行う
        return true;
      }
      return false;
    },
  },
});

上記のようにすることで、user@mycompany.comのような特定のドメインのアカウントのみがログインできるように制限することができます。

そのほか、signInにカスタム処理を追加し、ログイン日時の更新や新規ユーザーであればDBに追加するといった処理を実装することができます。

option:middlewareをさらにカスタマイズする

以下のようにコードを書くことで、

  1. セッションがない場合はログインページにリダイレクト
  2. セッションがある(ログイン済み)場合にログインページへ遷移しようとした場合はデフォルトページにリダイレクト

のような挙動を実現することもできます。

middleware.ts
export async function middleware(request: NextRequest) {
  const session = await auth();
  const { pathname } = request.nextUrl;

  if (!session && pathname !== '/login') {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  if (session && pathname === '/login') {
    return NextResponse.redirect(new URL('/dashboard', request.url));
  }

  return NextResponse.next();
}

まとめ

今回はAuth.jsを使った認証機能を爆速で実装する流れを解説しました。

Auth.jsは柔軟で使いやすく、セキュアな認証処理を提供してくれる優れたOSSです。


自分も全く知らない状態からAuth.jsを学習して1日で認証機能の実装ができました。

「認証機能に特にこだわりはない」「とにかく爆速で認証機能を実装したい」という人にはAuth.jsはかなりおすすめです!

ぜひAuth.jsについて勉強して、アプリケーションに実装して爆速で認証機能を実装してください!

最後までお読みいただきありがとうございました〜!


https://store.line.me/emojishop/author/5353830/ja

Discussion