Next.js全栈实战:手把手集成NextAuth实现Google/GitHub一键登录

Next.js全栈实战:手把手集成NextAuth实现Google/GitHub一键登录

🔥 前言

最近想搭建一个全栈应用,登录这部分功能希望是通过Google授权登录。我发现Next比较适合,集成了NextAuth,可以轻松实现各种身份验证和授权功能,无需手动处理令牌和会话,集成谷歌、github等常用平台登录,尝试搭建了下,简单跟大家分享下搭建过程和遇到的坑。

🛠️ 环境准备

确保项目已初始化Next.js并安装依赖:

bash 复制代码
npx create-next-app@latest
# or
yarn create next-app

如果你希望使用 TypeScript 开发项目,可以通过 --typescript 参数创建 TypeScript 项目:

bash 复制代码
npx create-next-app@latest --typescript
# or
yarn create next-app --typescript

创建成功后,运行 pnpm run dev 或 yarn dev 来启动开发服务器,访问地址为 http://localhost:3000, 可以看到项目已经启动成功,根据需求自行开发项目内容。

🌐 配置NextAuth核心文件

1. 创建API路由

在src/app目录下创建api/auth/[...nextauth]/route.ts文件

2. 安装依赖

在项目根目录下运行以下命令来安装所需的依赖:

bash 复制代码
pnpm add next-auth

3. 完善项目内容和Sign In按钮

自行在项目中开发具体的内容和搭建页面,下面是我的项目,已经实现了UI部分的功能。我需要在Sign In按钮上添加一个点击事件,当用户点击按钮时,跳转到第三方Google/GitHub授权登录

4. Sign In 按钮跳转到第三方

点击Sign In按钮,执行handleGoogleLogin,跳转google还是github

javascript 复制代码
await signIn('google', { 
  callbackUrl: callbackUrl,
});

5. 实现认证代码

在api/auth/[...nextauth]/route.ts文件中,实现认证逻辑。

🔑 申请google OAuth权限

看到当前的项目,我用红框圈起来的名字,点击可以创建项目,选择无组织

  • 第二步. 配置

点击左侧菜单栏的"API 和服务",然后点击"OAuth权限请求页面"

根据提示按步骤填写,受众群体选择外部

  • 第三步. 客户端配置

已获授权的 JavaScript 来源写

http://localhost:3000

已获授权的重定向 URI写

http://localhost:3000/api/auth/callback/google

https://上线后你的域名.com/api/auth/callback/google

  • 第四步.

创建成功后会生成客户端ID和客户端密钥,保存好,后面会放到环境变量中,授权的时候会调用

  • 第五步.

添加测试用户,把自己的google账户添加为测试用户

🔑 申请github OAuth权限

  • 第一步. 进入github 点击自己的头像,选择setting
  • 第二步.选择左侧底部的 Developer settings
  • 第二步.选择OAuth apps
  • 第三步. 按步骤填写

Homepage URL 写

http://localhost:3000

Authorization callback URL写

http://localhost:3000/api/auth/callback/github

点击Generate a new client secret生成秘钥,Client ID是你应用的ID,把id和秘钥也保存,后续配置到环境变量使用

📝 配置环境变量

在根目录创建.env环境变量文件,填写刚才拿到的google的id和秘钥以及github的id和秘钥

#NextAuth 核心配置

NEXTAUTH_URL=http://localhost:3000 //用的基础URL(用于OAuth回调) NEXTAUTH_SECRET=your_secure_secret_here //这个是随机生成的,用于加密会话令牌和CSRF令牌的密钥

#Google OAuth GOOGLE_CLIENT_ID=your_google_client_id GOOGLE_CLIENT_SECRET=your_google_secret

#GitHub OAuth GITHUB_CLIENT_ID=your_github_client_id GITHUB_CLIENT_SECRET=your_github_secret

💻 前端集成

之前的在api/auth/[...nextauth]/route.ts文件中,实现认证的逻辑就会用到id和秘钥

typescript 复制代码
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import GithubProvider from 'next-auth/providers/github';

const handler = NextAuth({
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_CLIENT_ID || "",
      clientSecret: process.env.GITHUB_CLIENT_SECRET || "",
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID || "",
      clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
    }),
  ],
  secret: process.env.NEXTAUTH_SECRET,
  debug: true, // 启用调试模式,以便查看详细的错误信息
  pages: {
    signIn: "/auth/signin",
    error: "/auth/error",
  },
  callbacks: {
    async session({ session, token }) {
      if (token && session.user) {
        // 扩展 session.user 类型以包含 id 属性
        (session.user as any) = {
          ...session.user,
          id: token.sub
        };
      }
      return session;
    },
    async jwt({ token, user, account }) {
      if (account && user) {
        console.log('OAuth账户信息:', {
          provider: account.provider,
          type: account.type,
          access_token: account.access_token?.slice(0, 10),
          id: user.id
        });
        token.accessToken = account.access_token;
        token.id = user.id;
      }
      return token;
    },
    async redirect({ url, baseUrl }) {
      // 默认行为:允许 NextAuth 处理 OAuth 重定向
      if (url.startsWith("/")) return `${baseUrl}${url}`;
      if (new URL(url).origin === baseUrl) return url;
      return baseUrl;
    },
    async signIn({ account, profile }) {
      console.log('OAuth请求目标URL:', account?.authorization_url);
      return true;
    }
  },
});
export { handler as GET, handler as POST };

🚀 效果演示

github授权登录

google授权登录

⚠️ 常见问题

1.google 链接chrome报错,ETIMEDOUT 93.46.8.90:443或者timeout 等问题

我尝试使用代理写到api/auth/[...nextauth]/route.ts中,如下操作,并没有起到作用

typeScript 复制代码
import { HttpsProxyAgent } from 'https-proxy-agent';
import { HttpProxyAgent } from 'http-proxy-agent';

const proxyUrl = process.env.HTTPS_PROXY || 'http://127.0.0.1:7890'; // 替换为你的代理地址
const httpAgent = new HttpProxyAgent(proxyUrl);
const httpsAgent = new HttpsProxyAgent(proxyUrl);
GoogleProvider({
  clientId: process.env.GOOGLE_CLIENT_ID || "",
  clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
  authorization: { params: { access_type: "offline" } },
  httpOptions: {
    proxy: httpsAgent
  }
})

还尝试使用fetch,某些代理环境对 node-fetch 更友好。尝试强制 NextAuth 使用 fetch,依然不起作用。

最后找出问题所在,使用代理的时候,要开全局,尤其是要强制开启TUN模式,应该大部分连不上还是代理这的问题

2.google超时问题可以把时间调大一点,时间太短容易超时

typescript 复制代码
GoogleProvider({
  clientId: process.env.GOOGLE_CLIENT_ID || "",
  clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
  httpOptions: {
    timeout: 50000 // 将超时时间增加到 10 秒
  }
})
相关推荐
Mr.Jessy1 分钟前
JavaScript高级:构造函数与原型
开发语言·前端·javascript·学习·ecmascript
白兰地空瓶2 小时前
🚀你以为你在写 React?其实你在“搭一套前端操作系统”
前端·react.js
爱上妖精的尾巴3 小时前
6-4 WPS JS宏 不重复随机取值应用
开发语言·前端·javascript
似水流年QC3 小时前
深入探索 WebHID:Web 标准下的硬件交互实现
前端·交互·webhid
陪我去看海3 小时前
测试 mcp
前端
speedoooo4 小时前
在现有App里嵌入一个AI协作者
前端·ui·小程序·前端框架·web app
全栈胖叔叔-瓜州4 小时前
关于llamasharp 大模型多轮对话,模型对话无法终止,或者输出角色标识User:,或者System等角色标识问题。
前端·人工智能
三七吃山漆4 小时前
攻防世界——wife_wife
前端·javascript·web安全·网络安全·ctf
用户47949283569154 小时前
面试官问"try-catch影响性能吗",我用数据打脸
前端·javascript·面试
GISer_Jing5 小时前
前端营销技术实战:数据+AI实战指南
前端·javascript·人工智能