言語を切り替える
テーマを切り替える

Next.js OAuth ログイン完全ガイド:Google、GitHub、WeChat 設定とベストプラクティス

「Google でログイン」をクリックし、Google にジャンプして、承認をクリックすると、また戻ってきて自動的にログイン成功。

このプロセス、何度も経験していますよね。でも、いざ自分のプロジェクトにサードパーティログインを追加しようとすると、突然頭が真っ白になります。「なぜ2回もジャンプするの?」「コールバック URL って何?」「redirect_uri_mismatch って何?」「ローカルテストでは正常なのに、デプロイしたらエラー?」

正直、私が初めて OAuth を設定した時もそうでした。大量のドキュメントを読みましたが、画面いっぱいの「認可コード」、「access_token」、「client_secret」といった専門用語に、読めば読むほど混乱しました。その後、丸2日かけて無数の落とし穴にはまり、ようやく理解できました。

この記事では、OAuth ログインについて最も平易な言葉で解説したいと思います。専門用語を並べるのではなく、実際にどう動いているのか、そしてNext.js で Google、GitHub、WeChat の3つのログインをどう設定するかについて話します。読み終わる頃には、実はそれほど難しくないことに気づくでしょう。

OAuth 2.0 とは結局何か?(人間語で解説)

生活の例で理解する

あなたがマンションに住んでいて、ネットで買った商品を配達員に玄関まで届けてもらいたいとします。でも問題があります。マンションにはオートロックがあり、配達員は入れません。

従来の方法はどうでしょう? あなたのカードキーを配達員に渡す? でもそれは危険ですよね。万が一配達員がカードキーを持っていれば、今後いつでもマンションに入れてしまいます。

もっと賢い方法はこれです:あなたが管理人に「荷物が来るから通して」と伝えます。管理人は配達員に一時通行証を発行します。「今日の午後2時から4時の間だけ、A棟にのみ入館可」と書かれています。配達が終われば、通行証は無効になります。

これが OAuth の核心思想です。

この例では:

  • あなた = ユーザー(ログインしたい人)
  • 配達員 = サードパーティアプリ(あなたが開発した Web サイトなど)
  • 管理人 = OAuth プロバイダー(Google、WeChat、GitHub など)
  • カードキー = あなたのパスワード(他人に渡してはいけない)
  • 一時通行証 = access_token(有効期限あり、権限制限あり)

あなたはパスワードをサードパーティアプリに渡す必要はなく、OAuth プロバイダーから「一時通行証」をもらう権限を与えるだけでいいのです。

OAuth の5ステップ(認可コードモード)

さて、このプロセスを Next.js OAuth ログインに具体化してみましょう。

ステップ1:ユーザーがあなたのサイトの「Google でログイン」ボタンをクリックします。

ステップ2:あなたのサイトはユーザーを Google の認可ページにリダイレクトします。URL はこんな感じです:

https://accounts.google.com/o/oauth2/auth?
  client_id=あなたのアプリID
  &redirect_uri=http://localhost:3000/api/auth/callback/google
  &response_type=code
  &scope=openid email profile
  &state=ランダム文字列

このステップで、あなたのサイトは Google にこう言っています。「ねえ、私は某アプリ(client_id)です。ユーザーがそちらのアカウントでログインしたいそうなので、確認をお願いします。確認が終わったら、ユーザーをこのアドレス(redirect_uri)に戻してください」

ステップ3:ユーザーは Google のページで「某アプリがあなたの基本情報へのアクセスを求めています」と見て、「許可」をクリックします。

ステップ4:Google はユーザーをあなたのサイト(redirect_uri)にリダイレクトして戻し、URL に**認可コード(code)**を添付します:

http://localhost:3000/api/auth/callback/google?code=ABCD1234&state=ランダム文字列

注意:この code は単なる引換券で、最終的な通行証ではありません。有効期限は非常に短く(通常10分)、一度しか使えません。

ステップ5:あなたのサイトのバックエンドは、この code とあなたの client_secret(パスワード)を持って、Google に本当の access_token をもらいに行きます:

// バックエンドコード(簡略版)
const response = await fetch('https://oauth2.googleapis.com/token', {
  method: 'POST',
  body: JSON.stringify({
    code: 'ABCD1234',
    client_id: 'あなたのアプリID',
    client_secret: 'あなたのアプリパスワード',
    redirect_uri: 'http://localhost:3000/api/auth/callback/google',
    grant_type: 'authorization_code',
  }),
})

const { access_token } = await response.json()

access_token を取得したら、あなたのサイトはそれを使って Google からユーザー情報(メール、アイコン、名前など)を取得できるようになります。

ステップ6(オプション):access_token を使ってユーザー情報を取得:

const userInfo = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
  headers: {
    Authorization: `Bearer ${access_token}`,
  },
})

全プロセスが完了すると、あなたのサイトは「このユーザーが誰か」を知り、セッションを作成してログイン状態にすることができます。

いくつかの重要な概念の解説

ここまで読んでも、いくつかの用語に戸惑うかもしれません。もう一度わかりやすく説明します。

  • client_id:Google におけるあなたのアプリの「ID番号」。公開されても問題ありません。

  • client_secret:あなたのアプリの「パスワード」。絶対に漏らしてはいけません。バックエンドでのみ使用します。もし他人が client_secret を入手したら、あなたのアプリになりすましてユーザー情報を取得できてしまいます。

  • redirect_uri:認可成功後、Google がユーザーを送り届けるアドレス。このアドレスは Google Cloud Console で事前に登録する必要があり、Google は厳密にチェックします。スラッシュが1つ多いだけでもエラーになります(そう、あの忌まわしき redirect_uri_mismatch です)。

  • state:CSRF 攻撃を防ぐためのランダムな文字列。認可開始時にこの state を生成し、Google はそれをそのまま返します。戻ってきた state が送ったものと同じかチェックし、違っていればリクエストが偽造された可能性があります。

  • code:一時的な認可コード。有効期限が短く(10分程度)、一度しか使えません。その役割は「ユーザーが Google で認可に同意した」ことの証明です。

  • access_token:真の「通行証」。これがあれば、あなたのサイトはユーザーに代わって Google から情報を取得できます。access_token にも有効期限があり、通常は1時間から数日です。

なぜ code と access_token の2段階に分けるのか?

なぜ直接 access_token を返さず、わざわざ code を使って交換するのか疑問に思うかもしれません。

鍵はセキュリティです。Code はブラウザのリダイレクト(フロントエンドで見える)を通じて渡されますが、access_token はバックエンドサーバー間(フロントエンドで見えない)で渡されます。もし URL で直接 access_token を返すと、ブラウザの履歴、ログ、ネットワーク監視などで漏洩する可能性があります。Code を token に交換する過程で client_secret が必要になりますが、client_secret はバックエンドにしか存在しないため、安全性ははるかに高くなります。

Next.js + NextAuth.js で Google ログイン設定(最も簡単な入門)

なぜ NextAuth.js を選ぶのか?

OAuth フローを自分で実装するのは実際かなり面倒です。コールバックの処理、セッション管理、CSRF 対策、トークン保存…細かいことが山積みです。

良い知らせは、NextAuth.js(現在は Auth.js v5)という専用のライブラリがあることです。GitHub で 15k+ スターを獲得しており、コミュニティは活発で、50以上の OAuth プロバイダー(Google、GitHub、WeChat、Twitter など)をサポートし、すぐに使えます。最新版は Next.js 14+ の App Router をサポートしており、設定は以前よりずっと簡単になりました。

要するに、NextAuth.js を使えば重複作業の80%を省けます。

ステップ1:Google Cloud でアプリを作成

コードを書く前に、Google でアプリを「登録」して、client_id と client_secret を取得する必要があります。

  1. Google Cloud Console を開き、Google アカウントでログインします。

  2. 初めて使う場合は、まずプロジェクト(Project)を作成します。名前は適当で構いません(例:「My Next.js App」)。

  3. 左側メニューから「API とサービス」→「認証情報」(Credentials)を探します。

  4. 「認証情報を作成」→「OAuth クライアント ID」を選択します。

  5. 初めての場合、「OAuth 同意画面」の設定を求められるかもしれません。アプリ名、サポートメールなどを入力し、他はスキップして構いません(ユーザータイプは「外部」を選択、テスト段階では審査不要)。

  6. OAuth クライアント ID の作成に戻り、アプリケーションの種類で「ウェブ アプリケーション」を選択します。

  7. ここが重要:「承認済みのリダイレクト URI」を設定します。2つのアドレスを入力します:

    • ローカル開発用:http://localhost:3000/api/auth/callback/google
    • 本番環境用(デプロイ後に追加):https://yourdomain.com/api/auth/callback/google

    注意:このアドレスはコード内のものと完全に一致している必要があります。スラッシュの有無ひとつで redirect_uri_mismatch エラーになります。私は最初ここでつまずきました。

  8. 「作成」をクリックすると、Client ID と Client Secret が表示されます。これらをコピーして、後で使います。

ステップ2:NextAuth.js のインストールと環境変数設定

Next.js プロジェクトで、パッケージをインストールします:

npm install next-auth@beta

注:v5(最新)を使うので @beta です。

プロジェクトルートに .env.local ファイルを作成し、取得した ID と Secret を記入します:

GOOGLE_CLIENT_ID=あなたのClient_ID.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=あなたのClient_Secret
NEXTAUTH_SECRET=ランダムな文字列を生成
NEXTAUTH_URL=http://localhost:3000

NEXTAUTH_SECRET は以下のコマンドで生成できます:

openssl rand -base64 32

本番環境にデプロイする際は、NEXTAUTH_URL をあなたのドメインに変更することを忘れずに。

ステップ3:NextAuth 設定ファイルの作成

app/api/auth/[...nextauth]/route.ts ファイルを作成します(Pages Router の場合は pages/api/auth/[...nextauth].ts):

import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"

export const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
  ],
  callbacks: {
    async signIn({ user, account, profile }) {
      // ログイン成功時のコールバック。ユーザー情報をDBに保存する処理などをここに書ける
      console.log("ユーザーログイン:", user)
      return true // true を返すとログイン許可
    },
    async session({ session, token }) {
      // セッション内容のカスタマイズ
      if (session.user) {
        session.user.id = token.sub // user id をセッションに追加
      }
      return session
    },
  },
}

const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }

これだけで、NextAuth.js が OAuth の全フローを自動処理してくれます。/api/auth/callback/google というルートも自動生成されるので、自分で書く必要はありません。

ステップ4:ログインボタンの作成

任意のコンポーネントで、ログインボタンをこのように書けます:

'use client' // App Router ではクライアントコンポーネント指定が必要

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

export default function LoginButton() {
  const { data: session } = useSession()

  if (session) {
    // ログイン済み
    return (
      <div>
        <p>ようこそ, {session.user?.name}</p>
        <img src={session.user?.image || ''} alt="アイコン" />
        <button onClick={() => signOut()}>ログアウト</button>
      </div>
    )
  }

  // 未ログイン
  return <button onClick={() => signIn('google')}>Google でログイン</button>
}

signIn('google') だけで Google 認可ページへジャンプし、完了後に戻ってきてログイン済みになります。超簡単です。

ステップ5:ルートレイアウトで SessionProvider をラップ

useSession を全コンポーネントで使えるように、ルートレイアウトを Provider でラップします:

// app/layout.tsx
import { SessionProvider } from "next-auth/react"

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        <SessionProvider>{children}</SessionProvider>
      </body>
    </html>
  )
}

完了!これで Google ログイン可能な Next.js アプリの出来上がりです。

よくある問題のトラブルシューティング

問題 1:redirect_uri_mismatch

これは最も一般的なエラーです。私も初回設定で遭遇しました。

エラーメッセージ例:Error 400: redirect_uri_mismatch

原因:Google Cloud Console で設定したコールバックアドレスと、実際のリクエストが一致していません。

解決策:

  1. Google Cloud Console の「承認済みのリダイレクト URI」が http://localhost:3000/api/auth/callback/google になっているか確認(スラッシュの有無に注意)。
  2. .env.localNEXTAUTH_URLhttp://localhost:3000 になっているか確認。
  3. ポートを変更した場合(例:3001)、両方変更する必要があります。

問題 2:ローカル開発は正常だが、デプロイ後にログイン失敗

これもよくあります。ローカルでは動くのに、Vercel に上げたらボタンを押しても反応なしかエラーになる。

原因:本番環境の環境変数を更新し忘れている。

解決策:

  1. Google Cloud Console の「承認済みのリダイレクト URI」に本番用ドメインを追加:https://yourdomain.com/api/auth/callback/google
  2. Vercel(または使用中のホスティング)の環境変数設定で、NEXTAUTH_URLhttps://yourdomain.com に変更。
  3. 再デプロイ。

問題 3:ログイン後 session が null

useSession() が常に null を返す場合、ルートレイアウトで <SessionProvider> をラップし忘れていないか確認してください。

問題 4:TypeError: Cannot read property ‘user’ of null

session がまだロード中なのに session.user にアクセスしようとしているのが原因です。

解決策:session が存在するか先にチェックする:

const { data: session, status } = useSession()

if (status === 'loading') {
  return <div>読み込み中...</div>
}

if (!session) {
  return <div>未ログイン</div>
}

// ここで安全に session.user にアクセス

GitHub ログイン設定(違いを理解する)

Google ログインの経験があれば、GitHub ログイン設定はずっと簡単です。ただ、Google とは少し違いがあるので説明します。

GitHub と Google OAuth の違い

似ている点:どちらも標準的な OAuth 2.0 認可コードモードで、フローは全く同じです。

異なる点:

  1. 権限管理が細かい:GitHub の scope(権限範囲)は Google より複雑です。デフォルトでは公開情報しか取れません。ユーザーのメールアドレス(特にプライベートアドレス)が必要な場合は、別途 user:email 権限を申請する必要があります。
  2. コールバック設定が緩い:Google は完全な URL を求めますが、GitHub はドメインを入力するだけで済みます。
  3. アプリタイプ:GitHub は個人アカウントと組織アカウントの2種類の OAuth App をサポートしています。

ステップ1:GitHub で OAuth App を作成

  1. GitHub にログインし、右上のアイコン → Settings → 左側メニュー下部 “Developer settings” を探します。

  2. “OAuth Apps” → “New OAuth App” をクリック。

  3. アプリ情報を入力:

    • Application name:アプリ名(ユーザー認可時に表示)
    • Homepage URL:サイトのトップページ(例:http://localhost:3000
    • Authorization callback URLhttp://localhost:3000/api/auth/callback/github と入力
  4. “Register application” をクリックし、“Generate a new client secret” をクリックして、Client ID と Client Secret をコピーします。

ステップ2:環境変数の設定

.env.local に GitHub の設定を追加:

GITHUB_CLIENT_ID=あなたのGitHub_Client_ID
GITHUB_CLIENT_SECRET=あなたのGitHub_Client_Secret

ステップ3:NextAuth 設定の更新

先ほどの route.ts ファイルに GitHubProvider を追加します:

import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import GitHubProvider from "next-auth/providers/github"

export const authOptions = {
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
    }),
    GitHubProvider({
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
      // プライベートメールを取得したい場合
      authorization: {
        params: {
          scope: 'read:user user:email'
        }
      }
    }),
  ],
  callbacks: {
    // ... 以前の callbacks
  },
}

const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }

ステップ4:ログインボタン更新

ログインボタンコンポーネントに GitHub オプションを追加:

return (
  <div>
    <button onClick={() => signIn('google')}>Google でログイン</button>
    <button onClick={() => signIn('github')}>GitHub でログイン</button>
  </div>
)

これで完了!

scope(権限範囲)についての補足

GitHub の scope はアプリが取得できる情報を制御します。よく使うもの:

  • read:user:ユーザーの公開・非公開情報(名前、アバター、bioなど)を読む
  • user:email:ユーザーのメールアドレス(非公開含む)を読む
  • public_repo:公開リポジトリにアクセス
  • repo:全リポジトリにアクセス(公開+非公開、権限が強すぎるので注意)

ログイン目的なら、read:user user:email で十分です。

もし user:email scope を付けないと、NextAuth.js は公開メールアドレスしか取得できません。ユーザーが GitHub 設定でメールを非公開にしていると、session.user.email が null になります。私はこれでしばらく悩み、コードが間違っているのかと疑いました。

小さな落とし穴:GitHub ユーザーは公開メールがない場合がある

Google(メール必須)と違い、GitHub ユーザーはメールを公開しない選択ができます。あなたのアプリがユーザーのメールを必須とする場合、signIn callback でチェックすることをお勧めします:

async signIn({ user, account }) {
  if (account?.provider === 'github' && !user.email) {
    // メール未公開ユーザー、拒否するか入力を促す
    console.log("GitHub ユーザーのメール未取得")
    return false // ログイン拒否
  }
  return true
}

WeChat(微信)ログイン設定(中国固有の事情)

さて、WeChat ログインについて話しましょう。正直、WeChat ログインは Google や GitHub よりかなり複雑です。エコシステムが国外と異なるためです。

WeChat ログインはなぜ特別か?

主な違い:

  1. 要スキャン:PC サイトの WeChat ログインは、ユーザーがスマホを取り出して QR コードをスキャンする必要があります(Google/GitHub のようにクリックで完結しない)。
  2. 公式 NextAuth.js Provider なし:NextAuth.js には組み込みの WeChat provider がなく、自作する必要があります。
  3. コールバックアドレス制限:WeChat はコールバックドメインの备案(ICP登録)を要求するため、localhost が使えず、開発デバッグが面倒です。
  4. openid と unionid:WeChat のユーザー識別は特殊で、同じユーザーでも異なるアプリでは openid が異なります。複数のアプリでユーザーを同定したい場合、unionid を使う必要があります。

ステップ1:WeChat オープンプロットフォーム登録

  1. WeChat オープンプロットフォームを開き、アカウント登録します。

  2. 「Web サイトアプリ(网站应用)」を作成します(公式アカウントやミニプログラムではありません)。

  3. サイト情報を入力、スクリーンショットをアップロードし、審査を待ちます。審査には通常1-3営業日かかります。

  4. 審査通過後、AppIDAppSecret が発行されます。

  5. 「開発情報」で認可コールバックドメインを設定します(ドメインのみ入力、yourdomain.com のように。パスは不要)。

ステップ2:WeChat Provider の自作

NextAuth.js にはないので、lib/wechat-provider.ts を作成します:

import type { OAuthConfig, OAuthUserConfig } from "next-auth/providers"

export interface WeChatProfile {
  openid: string
  nickname: string
  headimgurl: string
  sex: number
  province: string
  city: string
  country: string
  unionid?: string
}

export default function WeChatProvider<P extends WeChatProfile>(
  options: OAuthUserConfig<P>
): OAuthConfig<P> {
  return {
    id: "wechat",
    name: "WeChat",
    type: "oauth",
    
    // WeChat 認可アドレス(PCサイト用)
    authorization: {
      url: "https://open.weixin.qq.com/connect/qrconnect",
      params: {
        scope: "snsapi_login",
        appid: options.clientId,
        response_type: "code",
      },
    },
    
    // コードを access_token に交換するアドレス
    token: {
      url: "https://api.weixin.qq.com/sns/oauth2/access_token",
      params: {
        appid: options.clientId,
        secret: options.clientSecret,
        grant_type: "authorization_code",
      },
    },
    
    // ユーザー情報取得アドレス
    userinfo: {
      url: "https://api.weixin.qq.com/sns/userinfo",
      async request({ tokens, provider }) {
        const res = await fetch(
          `${provider.userinfo?.url}?access_token=${tokens.access_token}&openid=${tokens.openid}&lang=zh_CN`
        )
        return await res.json()
      },
    },
    
    // WeChat のユーザー情報を NextAuth 標準形式に変換
    profile(profile) {
      return {
        id: profile.openid,
        name: profile.nickname,
        email: null, // WeChat はメールを提供しない
        image: profile.headimgurl,
      }
    },
    
    options,
  }
}

ステップ3:環境変数設定

.env.local に WeChat 設定を追加:

WECHAT_CLIENT_ID=あなたのWeChat_AppID
WECHAT_CLIENT_SECRET=あなたのWeChat_AppSecret

ステップ4:NextAuth での使用

route.ts を更新:

import WeChatProvider from "@/lib/wechat-provider"

export const authOptions = {
  providers: [
    GoogleProvider({...}),
    GitHubProvider({...}),
    WeChatProvider({
      clientId: process.env.WECHAT_CLIENT_ID!,
      clientSecret: process.env.WECHAT_CLIENT_SECRET!,
    }),
  ],
}

ステップ5:ローカル開発でのテスト方法

これが最大の難所です。WeChat は localhost をコールバックドメインとして許可しないため、直接テストできません。

解決策は2つ:

案1:イントラネット貫通ツールを使用(推奨)

ngrokcpolar を使い、ローカルサービスを公開します:

# ngrok をインストール
brew install ngrok

# 起動
ngrok http 3000

ngrok は https://abc123.ngrok.io のような一時ドメインをくれます。これを WeChat オープンプロットフォームのコールバックドメインに設定し、.env.localNEXTAUTH_URL も更新します:

NEXTAUTH_URL=https://abc123.ngrok.io

案2:hosts ファイル設定

ローカルの hosts ファイル(Mac/Linux は /etc/hosts、Windows は C:\Windows\System32\drivers\etc\hosts)に一行追加:

127.0.0.1 dev.yourdomain.com

そして http://dev.yourdomain.com:3000 にアクセスし、WeChat プラットフォームでコールバックドメインを dev.yourdomain.com に設定します。

ただし、WeChat はコールバックドメインの备案(ICP登録)を要求するため、dev.yourdomain.com でも通らない場合があります。案1の方が確実です。

WeChat ログインの特殊処理

WeChat ユーザーにはメールがないため、アプリがメールに依存している場合は追加処理が必要です:

async signIn({ user, account }) {
  if (account?.provider === 'wechat') {
    // WeChat ユーザーはメールがないため、後で補完させるか
    // openid を一意の識別子として扱う
    console.log("WeChat ユーザー openid:", user.id)
  }
  return true
}

セキュリティ・ベストプラクティス(落とし穴回避)

OAuth 設定完了後、注意すべきセキュリティの詳細があります。これらも私が踏んで学んだ教訓です。

1. client_secret は絶対漏洩させない

間違い

// ❌ 絶対ダメ!
const clientSecret = "abc123def456" // コードにハードコード

client_secret をフロントエンドコードに書いたり Git にコミットしたりすると、他人がなりすまし可能になります。

正解

  • 環境変数に保存、.env.local.gitignore に入れる
  • client_secret はバックエンドでのみ使用(NextAuth.js の API route はバックエンドなのでOK)
  • デプロイ時はプラットフォームの環境変数管理機能を使用

2. state パラメータの役割(CSRF 防止)

OAuth フローには state パラメータがあり、CSRF 攻撃を防ぎます。

攻撃シナリオ:ハッカーが悪意あるリンク(偽の認可コード入り)を作り、クリックさせます。state 検証がないと、あなたのアプリはその偽コードを処理してしまうかもしれません。

幸い、NextAuth.js は state 検証を自動処理するので、追加コードは不要です。

自分で実装する場合(NextAuth.js 不使用)は:

  1. 認可開始時にランダムな state を生成し session か cookie に保存
  2. コールバック時に戻ってきた state が一致するか確認
  3. 不一致なら拒否

3. コールバックアドレスのホワイトリスト

OAuth プロバイダーの管理画面で、可能なコールバックアドレスをすべて設定しましょう:

  • 開発:http://localhost:3000/api/auth/callback/[provider]
  • プレビュー:https://preview.yourdomain.com/api/auth/callback/[provider]
  • 本番:https://yourdomain.com/api/auth/callback/[provider]

ワイルドカードは避けるhttps://*.yourdomain.com など)。便利ですが安全ではありません。

4. Token 保存の安全性

NextAuth.js はデフォルトで JWT を使い、token を HttpOnly Cookie に保存します。これは優れた設計です:

  • HttpOnly:JavaScript から読めないため、XSS 攻撃で盗まれません
  • Secure(本番):HTTPS のみで送信され、中間者攻撃を防ぎます

あなたのタスク:

  • access_token をフロントエンドに返さない(NextAuth.js はデフォルト通り、自分でも返さない)
  • ユーザー情報の永続化が必要なら、signIn callback で DB に保存し、session には最小限の情報(user id, email)のみ入れる

5. 認可コードの時効

認可コード(code)は短命(10分)で使い捨てです。

ハッカーが code を盗んでも、使う頃には期限切れか、あなたが使用済みで無効になっています。

ユーザーが認可画面で長時間放置した場合、戻った時には code が期限切れになっているかもしれません。NextAuth.js はこれを自動処理し、再認可を促します。

6. 本番環境チェックリスト

デプロイ前にチェック:

  • 環境変数は設定したか(NEXTAUTH_URL, NEXTAUTH_SECRET, 各 provider の id/secret)?
  • NEXTAUTH_URL は本番ドメインか(localhost でない)?
  • OAuth プロバイダーの本番用バックコールアドレスを設定したか?
  • .env.local は .gitignore に入っているか?
  • 本番の NEXTAUTH_SECRET はランダム生成したものか(開発環境の使い回しではない)?

まとめ

OAuth の本質は「一時通行証」です。パスワードを渡さず、OAuth プロバイダーから期限・権限付きの通行証(access_token)をもらう権限を与えるだけです。フローは2段階:まず認可コード(code)でユーザー同意を証明し、次に code + client_secret で本当の token と交換します。

Next.js での設定は、Google が一番簡単で入門に最適。GitHub は少し複雑で scope やメール非公開に注意。WeChat は最も特殊で、スキャン、自作 provider、备案ドメインなどハードルが高いです。

セキュリティの3原則:

  1. client_secret はバックエンドのみ、漏洩厳禁
  2. state パラメータ検証(NextAuth.js が代行)
  3. コールバックアドレスはホワイトリスト化

初挑戦なら、まずは Google ログインから始め、記事の手順通りに進めることをお勧めします。設定成功の達成感は格別です。

トラブル時は慌てずに。90%のエラーは redirect_uri 不整合か環境変数設定ミスです。見直せば解決します。

最後に NextAuth.js 公式ドキュメント も参照してください。DB セッション保存、カスタムログインページ、JWT 設定など高度な使い方が載っています。OAuth 2.0 仕様(RFC 6749)も原理理解に役立ちます。

ぜひ試してみてください。スムーズな設定を祈ります!

Next.js OAuth サードパーティログイン設定完全フロー

ゼロから Google、GitHub、WeChat の3つのサードパーティログインを設定する

⏱️ Estimated time: 2 hr

  1. 1

    Step1: NextAuth.js のインストールと初期化

    依存関係のインストール:
    • npm install next-auth
    • app/api/auth/[...nextauth]/route.ts を作成

    基本設定:
    • NEXTAUTH_URL を設定(ローカル:http://localhost:3000、本番:実ドメイン)
    • NEXTAUTH_SECRET を設定(ランダム文字列生成)
    • providers 配列を構成
  2. 2

    Step2: Google ログインの設定

    手順:
    1. Google Cloud Console にアクセス
    2. OAuth クライアント ID を作成
    3. 承認済みリダイレクト URI を設定:http://localhost:3000/api/auth/callback/google
    4. Client ID と Client Secret を取得
    5. 環境変数に追加:GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
    6. NextAuth 設定に GoogleProvider を追加

    注意:本番環境のコールバックアドレスは設定と完全一致が必須
  3. 3

    Step3: GitHub ログインの設定

    手順:
    1. GitHub Settings > Developer settings > OAuth Apps へアクセス
    2. 新しい OAuth App を作成
    3. Authorization callback URL を設定:http://localhost:3000/api/auth/callback/github
    4. Client ID と Client Secret を取得
    5. 環境変数に追加:GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET
    6. NextAuth 設定に GitHubProvider を追加

    注意:メール取得には scope に user:email が必要
  4. 4

    Step4: WeChat ログインの設定(オプション)

    手順:
    1. WeChat オープンプロットフォームアカウント登録(企業認証要)
    2. Web サイトアプリを作成、AppID と AppSecret 取得
    3. 認可コールバックドメインを設定(备案要)
    4. Provider を自作(NextAuth 非内蔵)
    5. スキャンログイン実装

    注意:WeChat ログインは複雑なので、Google/GitHub 完了後の挑戦を推奨
  5. 5

    Step5: ログインページとボタンの作成

    ログインコンポーネント作成:
    • signIn('google') でログイン開始
    • signOut() でログアウト
    • useSession() でユーザー情報取得
    • SessionProvider でアプリをラップ

    例:
    <button onClick={() => signIn('google')}>
    Google でログイン
    </button>
  6. 6

    Step6: テストとデバッグ

    テストポイント:
    • ローカル:コールバックアドレスが http://localhost:3000 であるか
    • 本番:コールバックアドレスが実ドメインと一致するか
    • 環境変数は正しく設定されているか
    • ブラウザコンソールとサーバーログを確認

    よくあるエラー:
    • redirect_uri_mismatch:アドレス不一致
    • invalid_client:Client ID/Secret 間違い
    • access_denied:ユーザー認可拒否

FAQ

OAuth 2.0 の仕組みとは?
OAuth 2.0 はユーザーがパスワードを提供せずに、サードパーティアプリにリソースへのアクセスを許可する仕組みです。流れ:ログインクリック → OAuth プロバイダーへジャンプ → ユーザー認可 → 認可コード返却 → コードを access_token に交換 → token でユーザー情報取得。
redirect_uri_mismatch エラーの解決法は?
コールバックアドレス不一致のエラーです。
解決法:
1) OAuth プロバイダー設定のコールバックアドレスと、コード内のものが(プロトコル、ドメイン、ポート、パスまで)完全に一致しているか確認
2) ローカルは http://localhost:3000、本番は実ドメインを使用
3) 不要なスラッシュやパラメータがないか確認
NextAuth.js と手動実装の違いは?
NextAuth.js はパッケージ化された OAuth ソリューションです:
• 50+ プロバイダーサポート
• 認可フロー、セッション管理、CSRF 対策を自動処理

手動実装は以下を自前処理する必要があります:
• 認可コード交換
• token 保存
• state 検証など
コード量が多くエラーになりやすいため、NextAuth.js 推奨です。
ユーザーのメールアドレスを取得するには?
プロバイダーにより異なります:
• Google:デフォルトで返却
• GitHub:scope に user:email が必要、かつユーザーが公開設定している必要あり
• WeChat:unionid での照会が必要

取得できない場合は、ログイン後に手動入力を促す必要があります。
ローカルではOKで、本番デプロイ後にエラーになるのはなぜ?
通常はコールバックアドレス設定の問題です。
確認事項:
1) 本番環境の NEXTAUTH_URL が正しいか
2) OAuth プロバイダー設定に本番ドメインが含まれているか
3) 環境変数が正しく設定されているか
4) ファイアウォールやプロキシの影響がないか
複数のログイン方式を併用できますか?
はい。NextAuth.js は複数の providers 設定をサポートしており、ユーザーは Google、GitHub、WeChat などから好きな方式を選べます。signIn() 関数でプロバイダー名を指定するだけです。
OAuth ログインは安全ですか?
OAuth 2.0 は業界標準であり比較的安全です。
注意点:
1) client_secret はサーバーサイドでのみ使用し、漏洩させない
2) state パラメータで CSRF を防ぐ(NextAuth.js は自動処理)
3) コールバックアドレスはホワイトリスト化し、ワイルドカードを使わない
4) 定期的に依存パッケージを更新する

8 min read · 公開日: 2025年12月19日 · 更新日: 2026年1月22日

コメント

GitHubアカウントでログインしてコメントできます

関連記事