NextAuth

623 阅读6分钟
import GitHub from "@auth/core/providers/github";
import NextAuth from "next-auth";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { db } from "./db";

const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID;
const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET;
if (!GITHUB_CLIENT_ID || !GITHUB_CLIENT_SECRET) {
  throw new Error("Missing github oauth credentials");
}
export const {
  handlers: { GET, POST },
  auth,
  signIn,
  signOut,
} = NextAuth({
  adapter: PrismaAdapter(db),
  providers: [
    GitHub({
      clientId: GITHUB_CLIENT_ID,
      clientSecret: GITHUB_CLIENT_SECRET,
    }),
  ],
  callbacks: {
    //
    async session({ session, user }: any) {
      if (session && user) {
        session.user.id = user.id;
      }
      return session;
    },
  },
});

这段代码是用于配置 Next.js 应用中的身份验证系统,具体使用的是 NextAuth.js 框架,配合 GitHub OAuth 提供者和 Prisma ORM。我将逐行解释代码及其功能:

导入部分

javascriptCopy code
import GitHub from "@auth/core/providers/github";
  • 导入 NextAuth.js 的 GitHub 提供者。这是一个预配置的提供者,用于集成 GitHub 的 OAuth 认证。
javascriptCopy code
import NextAuth from "next-auth";
  • 导入 NextAuth.js 库。NextAuth.js 是一个用于简化 Next.js 应用中身份验证的库。
javascriptCopy code
import { PrismaAdapter } from "@auth/prisma-adapter";
  • 导入 Prisma 适配器。Prisma 是一个数据库 ORM,Prisma 适配器用于将 NextAuth.js 与 Prisma ORM 集成。
javascriptCopy code
import { db } from "./db";
  • 导入数据库实例。假设 ./db 文件中导出了一个配置好的 Prisma 数据库实例。

环境变量和校验

javascriptCopy code
const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID;
const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET;
  • 从环境变量中获取 GitHub 客户端 ID 和密钥。这些是用于 GitHub OAuth 流程的凭据。
javascriptCopy code
if (!GITHUB_CLIENT_ID || !GITHUB_CLIENT_SECRET) {
  throw new Error("Missing github oauth credentials");
}
  • 检查是否成功获取了这些凭据。如果没有,抛出一个错误。这是确保应用在缺少必要配置时不会运行的一种方式。

NextAuth 配置

javascriptCopy code
export const { handlers: { GET, POST }, auth, signIn, signOut } = NextAuth({
  • 这行代码初始化 NextAuth,并且解构出一些有用的属性和方法。这包括 HTTP GET 和 POST 请求的处理程序,以及 auth, signIn, signOut 方法。
javascriptCopy code
  adapter: PrismaAdapter(db),
  • 使用 PrismaAdapter 将 NextAuth 连接到 Prisma 数据库。这里的 db 是前面从 ./db 导入的 Prisma 实例。
javascriptCopy code
  providers: [GitHub({ clientId: GITHUB_CLIENT_ID, clientSecret: GITHUB_CLIENT_SECRET })],
  • 定义身份验证提供者。在这个例子中,配置了 GitHub 作为唯一的提供者,并使用了之前从环境变量中获取的凭据。

回调函数配置

javascriptCopy code
  callbacks: {
    async session({ session, user }: any) {
      if (session && user) {
        session.user.id = user.id;
      }
      return session;
    },
  },
});
  • callbacks 配置中,定义了一个 session 回调函数。当身份验证成功后,NextAuth 会调用这个函数,并传入用户会话和用户对象。在这个函数里,我们将用户 ID 添加到会话对象中。这样可以在应用的其他部分方便地访问当前登录用户的 ID。

总结

整体来看,这段代码配置了 Next.js 应用中的身份验证系统,使用了 NextAuth.js 与 GitHub OAuth 进行用户认证,并利用 Prisma ORM 管理用户数据。这种配置使得用户可以使用他们的 GitHub 账户登录到你的应用,并且你的应用能够在后台处理用户数据,例如保存用户会话信息。通过使用 Prisma 适配器,NextAuth.js 可以轻松地将用户信息存储到你的数据库中。

通过 NextAuth 配置解构出来的 handlers(包含 GETPOST)、authsignIn、和 signOut 函数是为了处理身份验证相关的操作。让我为你提供一些使用这些函数的实际示例:

1. 使用 handlersGETPOST

handlers 中的 GETPOST 是为了处理 NextAuth 相关的 HTTP 请求。这在 Next.js 的 API 路由中特别有用。例如,你可以在 pages/api/auth/[...nextauth].js 中使用这些处理程序来处理身份验证请求:

javascriptCopy code
// pages/api/auth/[...nextauth].js
import { handlers } from "path-to-your-auth-config";

export default function authHandler(req, res) {
  if (req.method === 'GET') {
    handlers.GET(req, res);
  } else if (req.method === 'POST') {
    handlers.POST(req, res);
  } else {
    res.status(405).end();
  }
}

在这个例子中,authHandler API 路由会根据请求的 HTTP 方法(GET 或 POST)调用相应的处理程序。

2. 使用 auth

auth 是一个帮助函数,通常用于在 API 路由中快速实现身份验证逻辑。例如,在一个受保护的 API 路由中,你可以使用它来验证用户会话:

javascriptCopy code
// pages/api/protected.js
import { auth } from "path-to-your-auth-config";

export default async function protectedHandler(req, res) {
  const session = await auth(req, res);
  if (!session) {
    return res.status(401).json({ error: '未经授权' });
  }

  res.status(200).json({ secret: '这是一个秘密信息' });
}

3. 使用 signInsignOut

signInsignOut 函数用于在你的应用中手动处理登录和登出流程。通常,在某些交互中,你可能希望让用户能够点击一个按钮来登录或登出。

jsxCopy code
// 任意 React 组件
import { signIn, signOut } from 'path-to-your-auth-config';

function MyComponent() {
  return (
    <div>
      <button onClick={() => signIn('github')}>使用 GitHub 登录</button>
      <button onClick={() => signOut()}>登出</button>
    </div>
  );
}

在这个组件中,用户可以点击按钮来启动登录(使用 GitHub)或登出过程。

总结

通过解构出的这些函数,你可以在 Next.js 应用中灵活地处理身份验证相关的操作,无论是在 API 路由中还是在用户界面中。这样,你就能根据用户交互或应用需求,灵活地集成和管理用户身份验证流程。

callbacks: { session }

在你的 NextAuth 配置中的 session 回调具有以下作用:

  • 目的:该回调函数在创建会话时被调用,并允许你自定义会话对象。

  • 参数sessionusersession 是当前的会话对象,而 user 是当前登录用户的用户对象。

  • 代码逻辑

    • 检查 sessionuser 对象是否存在。
    • 如果它们都存在,那么把 user 对象中的 id 属性添加到 session.user 对象中。这样可以在会话中轻松访问用户的 ID。
  • 应用场景:这通常用于将额外的用户信息(如用户 ID)添加到会话对象中,使得可以在整个应用中访问这些信息。

使用 pages/api/auth/[...nextauth].js

pages/api/auth/[...nextauth].js 是 Next.js 的动态路由功能的一部分,用于处理所有与 NextAuth 相关的 HTTP 请求。[...nextauth] 表示捕获所有以 auth 开头的 API 路径。

  • 如何工作:当你向 /api/auth/signin/api/auth/signout/api/auth/callback/github 等路径发出请求时,这些请求都会被路由到 pages/api/auth/[...nextauth].js 文件。
  • NextAuth.js 集成:在这个文件中,你可以利用 NextAuth.js 提供的 GETPOST 处理程序来处理不同类型的请求,这包括用户登录、登出以及身份验证回调。

示例 pages/api/auth/[...nextauth].js

这是一个 pages/api/auth/[...nextauth].js 文件的基本示例:

javascriptCopy code
// pages/api/auth/[...nextauth].js
import NextAuth from 'next-auth';

export default (req, res) => {
  // NextAuth.js 会处理 `/api/auth/*` 下的所有路由
  return NextAuth(req, res, {
    // ...你的 NextAuth 配置
  });
};

在这个文件中,NextAuth.js 处理所有 /api/auth/* 路径下的请求。你可以在这里配置身份提供者、回调、数据库适配器等。

总结

session 回调在 NextAuth.js 中用于定制会话对象,使你能夠在会话中添加额外的用户信息。而 pages/api/auth/[...nextauth].js 则是使用 Next.js 的动态路由来集中处理所有与身份验证相关的请求,通过 NextAuth.js 管理这些请求。这种集中式处理简化了身份验证的配置和管理。