[Next.js14] NextAuth v5 (1) - 登入/登出

王大冶發表於2024-10-27
  • React Hook 深入淺出
  • CSS技巧與案例詳解
  • vue2與vue3技巧合集
  • VueUse原始碼解讀

這是一篇關於在 Next.js 14 中使用 NextAuth v5(beta版)的實踐教程。由於 NextAuth v5 還處於 beta 階段,相關文件和資料比較少。本文結合了 Next.js 14 官方文件以及實際開發經驗。

一、環境搭建

1. 建立專案

使用以下命令建立一個新的 Next.js 專案:

npx create-next-app@latest

本專案採用以下技術棧:

  • TypeScript
  • Tailwind CSS
  • src/ 目錄結構
  • App Router 路由方案

2. 安裝依賴

安裝 NextAuth beta 版:

npm install next-auth@beta

確保 package.json 中的版本號不低於 ^5.0.0-beta.4

3. 生成金鑰

使用 openssl 生成認證金鑰:

openssl rand -base64 32

⚠️ 注意: 該金鑰需要妥善保管,不要提交到程式碼倉庫中

4. 配置環境變數

建立 .env 檔案並新增認證金鑰:

# .env
AUTH_SECRET=你的金鑰

記得將 .env 新增到 .gitignore 中。

二、專案結構

image.png

在基礎的 Next.js 專案中需要新增以下檔案:

src/
  ├── app/
  │   └── login/        # 登入頁面
  ├── lib/             # 工具函式
  ├── auth.config.ts   # 認證配置
  ├── auth.ts          # NextAuth 配置
  └── middleware.ts    # 中介軟體配置

三、主要頁面實現

Login 頁面

// src/app/login/page.tsx
"use client"

export default function Page() {
  return (
    <div>
      <h1>Log in Page</h1>
      <form className="flex flex-col">
        <input className="bg-blue-300 text-black" name="id" />
        <input 
          className="bg-yellow-300 text-black" 
          name="password" 
          type="password"
        />
        <button>Log In</button>
      </form>
    </div>
  )
}

Home 頁面

// src/app/page.tsx
export default async function Home() {
  return (
    <div>
      <h1>Home Page</h1>
      <h2>Unavailable without auth</h2>
      <form>
        <button>Log Out</button>
      </form>
    </div>
  )
}

使用npx next dev或npm run dev或 yarn 執行應用程式。

http://localhost:3000/login

image.png

http://localhost:3000/

image.png

四、許可權認證配置

1. 使用者型別定義

// src/lib/definitions.ts
export type User = {
    id: string
    email: string
    name: string
};

2. 認證配置

// src/auth.config.ts
import type { NextAuthConfig } from 'next-auth';

export const authConfig = {
  pages: {
    signIn: '/login',
  },
  callbacks: {
    authorized({ auth, request: { nextUrl } }) {
      const isLoggedIn = !!auth?.user;
      const isOnProtected = !nextUrl.pathname.startsWith('/login');
      
      if (isOnProtected) {
        if (isLoggedIn) return true;
        return false; // 重定向到登入頁
      } else if (isLoggedIn) {
        return Response.redirect(new URL('/', nextUrl));
      }
      return true;
    },
  },
  providers: [], 
};

3. NextAuth 初始化

// src/auth.ts
import NextAuth from 'next-auth';
import { authConfig } from './auth.config';
import Credentials from 'next-auth/providers/credentials';

export const { signIn, signOut } = NextAuth({
  ...authConfig,
  providers: [
    Credentials({
      async authorize(credentials) {
        if (credentials.id && credentials.password) {
          // 這裡新增實際的登入邏輯
          let loginRes = {
            success: true,
            data: {
              user: {
                ID: "john_doe",
                NAME: "John Doe", 
                EMAIL: "email@email.email",
              },
            }
          }
          if (!loginRes.success) return null;
          
          return {
            id: loginRes.data.user.ID,
            name: loginRes.data.user.NAME,
            email: loginRes.data.user.EMAIL,
          };
        }
        return null;
      },
    })
  ],
  callbacks: {
    async session({ session, token }) {
      session.user = token.user as User;
      return session;
    },
    async jwt({ token, user }) {
      if (user) {
        token.user = user;
      }
      return token;
    },
  },
});

4. 中介軟體配置

// src/middleware.ts
import NextAuth from 'next-auth';
import { authConfig } from './auth.config';

export default NextAuth(authConfig).auth;

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
};

5. 結果

在未登入的情況下前往http://localhost:3000/

image.png

我們被重定向到登入頁面。然後隨便輸入:

image.png

然後點選 "登入 "按鈕

image.png

五、部署注意事項

部署前需要在 .env 中配置以下環境變數:

NEXTAUTH_URL=${部署域名}
NEXT_PUBLIC_API_URL=${部署域名}

⚠️ 如果不配置這些變數,回撥 URL 會預設使用 localhost:3000 導致報錯。

以上就是在 Next.js 14 中整合 NextAuth v5 的完整實現流程。目前示例中使用了硬編碼的使用者資料,實際專案中需要根據後端 API 修改登入邏輯和使用者型別定義。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章