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权限
- 第一步. 谷歌云控制台 进入Google Cloud
看到当前的项目,我用红框圈起来的名字,点击可以创建项目,选择无组织

- 第二步. 配置
点击左侧菜单栏的"API 和服务",然后点击"OAuth权限请求页面" 
根据提示按步骤填写,受众群体选择外部 

- 第三步. 客户端配置

已获授权的 JavaScript 来源写
已获授权的重定向 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 写
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 秒
}
})