Next.js OAuth 登录完整指南:Google、GitHub、微信第三方登录配置与最佳实践
点击”使用 Google 登录”,页面跳转到 Google,点击授权,又跳回来,就自动登录成功了。
这个过程你肯定经历过无数次。但当你自己想给项目加个第三方登录时,突然就懵了:为什么要跳转两次?什么是回调地址?redirect_uri_mismatch 是什么鬼?本地测试正常,部署到线上就报错?
说实话,我第一次配置 OAuth 的时候也是这样。看了一堆文档,满屏都是”授权码”、“access_token”、“client_secret”这些术语,越看越晕。后来花了两天时间,踩了无数个坑,才算勉强搞明白。
这篇文章,我想用最直白的话讲清楚 OAuth 登录这件事。不堆砌术语,不讲大道理,就聊聊它到底是怎么工作的,以及怎么在 Next.js 里配置 Google、GitHub、微信三种登录。读完你会发现,其实也没那么玄乎。
OAuth 2.0 到底是什么?(用人话讲清楚)
先用个生活例子理解
假设你住在小区里,某天你在网上买了个东西,想让快递员帮你送到家门口。但问题来了:小区有门禁,快递员进不来。
传统做法是什么?你把门禁卡给快递员。但这样有风险啊——万一快递员拿着你的卡,以后随时能进小区怎么办?
更聪明的做法是:你去找小区保安,说”我有个快递要进来”。保安给快递员发了张临时通行证,上面写着”只能今天下午2点到4点进入,只能去A栋”。快递送完,通行证就失效了。
这就是 OAuth 的核心思想。
在这个例子里:
- 你 = 用户(想登录的人)
- 快递员 = 第三方应用(比如你开发的网站)
- 小区保安 = OAuth 提供者(Google、微信、GitHub等)
- 门禁卡 = 你的密码(不能给别人)
- 临时通行证 = access_token(有时效、有权限限制)
你不需要把密码给第三方应用,只需要授权它去 OAuth 提供者那里拿一张”临时通行证”。
OAuth 的五步流程(授权码模式)
好,现在我们把这个流程具体化到 Next.js OAuth 登录。
第一步:用户点击你网站上的”使用 Google 登录”按钮。
第二步:你的网站把用户重定向到 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)。”
第三步:用户在 Google 页面看到”某某应用想访问你的基本信息”,点击”允许”。
第四步:Google 把用户重定向回你的网站(redirect_uri),并在 URL 里带上一个授权码(code):
http://localhost:3000/api/auth/callback/google?code=ABCD1234&state=随机字符串
注意,这个 code 只是个凭证,不是最终的通行证。它的有效期很短(通常 10 分钟),而且只能用一次。
第五步:你的网站后端拿着这个 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 获取用户信息(邮箱、头像、名字等)了。
第六步(可选):用 access_token 获取用户信息:
const userInfo = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
headers: {
Authorization: `Bearer ${access_token}`,
},
})
整个流程走完,你的网站就知道”这个用户是谁”了,可以创建 session,让用户进入登录状态。
几个关键概念的人话解释
看到这里,你可能还是对几个术语有点迷糊。我再通俗地解释一遍:
-
client_id:你的应用在 Google 那里的”身份证号”。可以公开,别人看到也没事。
-
client_secret:你的应用的”密码”。绝对不能泄露,只能在后端使用。如果别人拿到了你的 client_secret,他们就能冒充你的应用去获取用户信息。
-
redirect_uri:授权成功后,Google 把用户送回哪个地址。这个地址必须提前在 Google Cloud Console 里注册,Google 会严格校验,哪怕多了一个斜杠都会报错(没错,就是那个让人抓狂的 redirect_uri_mismatch)。
-
state:一个随机字符串,用来防止 CSRF 攻击。你在发起授权时生成这个 state,Google 会原样返回。你要检查返回的 state 和你发出去的是不是同一个,如果不是,说明这个请求可能是伪造的。
-
code:临时授权码。有效期很短(10分钟左右),只能用一次。它的作用就是证明”用户已经在 Google 那里同意授权了”。
-
access_token:真正的”通行证”。有了它,你的网站就可以代表用户去 Google 获取信息。access_token 也有有效期,通常是 1 小时到几天不等。
为什么要分 code 和 access_token 两步?
你可能会想,为什么不直接返回 access_token,还要多此一举用个 code 再去换?
关键在于安全。Code 是通过浏览器重定向传递的(前端能看到),而 access_token 是在后端服务器之间传递的(前端看不到)。如果直接在 URL 里返回 access_token,浏览器历史记录、日志、网络监控都可能泄露它。用 code 换 token 的过程需要 client_secret,而 client_secret 只存在后端,这样就安全多了。
Next.js + NextAuth.js 配置 Google 登录(最简单的入门)
为什么选 NextAuth.js?
自己实现 OAuth 流程其实挺麻烦的:要处理回调、管理 session、防 CSRF 攻击、存储 token…一堆细节。
好消息是,有个库叫 NextAuth.js(现在叫 Auth.js v5)专门干这个事。它在 GitHub 上有 15k+ stars,社区很活跃,支持 50 多种 OAuth 提供者(Google、GitHub、微信、Twitter 等等),开箱即用。最新版本支持 Next.js 14+ 的 App Router,配置起来比以前简单多了。
说白了,用 NextAuth.js 能帮你省掉 80% 的重复劳动。
第一步:在 Google Cloud 创建应用
在写代码之前,你得先去 Google 那里”注册”一下你的应用,拿到 client_id 和 client_secret。
-
打开 Google Cloud Console,登录你的 Google 账号。
-
如果你之前没用过,先创建一个项目(Project)。项目名随便起,比如”My Next.js App”。
-
在左侧菜单找到”API 和服务” → “凭据”(Credentials)。
-
点击”创建凭据” → 选择”OAuth 客户端 ID”。
-
如果第一次用,可能会要求你先配置”OAuth 同意屏幕”。填一下应用名称、支持邮箱就行,其他先跳过(选”外部”用户类型,测试阶段不用审核)。
-
回到创建 OAuth 客户端 ID,选择应用类型为”Web 应用”。
-
重点来了:配置”已获授权的重定向 URI”。这里要填两个地址:
- 本地开发:
http://localhost:3000/api/auth/callback/google - 生产环境(部署后再加):
https://yourdomain.com/api/auth/callback/google
注意,这个地址必须和你代码里的完全一致,多一个斜杠、少一个斜杠都会报 redirect_uri_mismatch 错误。我刚开始就在这栽过跟头。
- 本地开发:
-
点击”创建”,会弹出一个对话框显示你的 Client ID 和 Client Secret。把这两个值复制下来,一会要用。
第二步:安装 NextAuth.js 并配置环境变量
在你的 Next.js 项目里,先装个包:
npm install next-auth@beta
注意要装 @beta 版本,这是 v5 版本(最新的)。
然后在项目根目录创建 .env.local 文件,把刚才拿到的 Client 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 改成你的域名。
第三步:创建 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 }) {
// 登录成功时的回调,可以在这里保存用户信息到数据库
console.log("用户登录:", user)
return true // 返回 true 表示允许登录
},
async session({ session, token }) {
// 自定义 session 内容
if (session.user) {
session.user.id = token.sub // 把 user id 加到 session 里
}
return session
},
},
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
就这样,NextAuth.js 会自动帮你处理 OAuth 的所有流程。/api/auth/callback/google 这个路由也是自动生成的,不用你再写代码。
第四步:创建登录按钮
在任意组件里,你可以这样写登录按钮:
'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 授权页面,授权完成后跳回来,用户就登录了。超简单。
第五步:在根布局里包裹 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 配置的回调地址和实际请求的不一致。
解决方法:
- 检查 Google Cloud Console 里的”已授权的重定向 URI”是不是
http://localhost:3000/api/auth/callback/google(注意有没有多余的斜杠) - 检查你的
.env.local里NEXTAUTH_URL是不是http://localhost:3000 - 如果你改了端口(比如 3001),两边都要改
问题 2:本地开发正常,部署后登录失败
这个我也踩过坑。本地测试登录一切正常,部署到 Vercel 后,点击登录按钮没反应或报错。
原因:忘了更新生产环境的环境变量。
解决方法:
- 在 Google Cloud Console 的”已授权的重定向 URI”里加上生产域名:
https://yourdomain.com/api/auth/callback/google - 在 Vercel(或你用的托管平台)的环境变量设置里,把
NEXTAUTH_URL改成https://yourdomain.com - 重新部署
问题 3:登录后 session 是 null
如果你调用 useSession() 返回的 session 一直是 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 登录就简单多了。不过 GitHub 和 Google 还是有点小差异,值得聊聊。
GitHub 和 Google OAuth 的区别
相似的地方:都是标准的 OAuth 2.0 授权码模式,流程一模一样。
不同的地方:
- 权限控制更细:GitHub 的 scope(权限范围)比 Google 复杂。默认只能拿到用户的公开信息,如果你想获取用户的邮箱(尤其是私有邮箱),需要单独申请
user:email权限。 - 回调地址配置更宽松:Google 要求你填写完整的回调 URL,GitHub 只需要填域名就行。
- 应用类型:GitHub 支持个人账号和组织账号两种 OAuth App。
第一步:在 GitHub 创建 OAuth App
-
登录 GitHub,点击右上角头像 → Settings → 左侧菜单找到 “Developer settings”。
-
点击 “OAuth Apps” → “New OAuth App”。
-
填写应用信息:
- Application name:你的应用名称(用户授权时会看到)
- Homepage URL:你的网站首页,比如
http://localhost:3000 - Authorization callback URL:填
http://localhost:3000/api/auth/callback/github
-
点击 “Register application”,然后点击 “Generate a new client secret”,把 Client ID 和 Client Secret 复制下来。
第二步:配置环境变量
在 .env.local 里加上 GitHub 的配置:
GITHUB_CLIENT_ID=你的GitHub_Client_ID
GITHUB_CLIENT_SECRET=你的GitHub_Client_Secret
第三步:更新 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 }
第四步:更新登录按钮
在登录按钮组件里,加上 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
}
微信登录配置(国内特殊情况)
好,现在来聊聊微信登录。说实话,微信登录比 Google 和 GitHub 复杂不少,主要是因为它的生态和国外的不太一样。
微信登录为什么特殊?
先说几个关键差异:
- 需要扫码:PC 网站的微信登录,用户需要掏出手机扫二维码授权(不像 Google/GitHub 直接在网页上点点点就行)。
- 没有官方 NextAuth.js Provider:NextAuth.js 没有内置微信 provider,你得自己写一个。
- 回调地址限制多:微信要求回调域名必须备案,不能用 localhost,开发调试比较麻烦。
- 有 openid 和 unionid:微信的用户标识比较特殊,同一个用户在不同应用里的 openid 不同,如果你有多个应用想共享用户数据,需要用 unionid。
第一步:微信开放平台注册
-
打开 微信开放平台,注册一个账号。
-
创建”网站应用”(注意不是公众号也不是小程序)。
-
填写网站信息,上传网站截图,等待审核。审核通常需要 1-3 个工作日。
-
审核通过后,你会拿到 AppID 和 AppSecret(相当于 client_id 和 client_secret)。
-
在”开发信息”里配置授权回调域(注意只填域名,不需要完整路径,比如
yourdomain.com)。
第二步:自定义微信 Provider
因为 NextAuth.js 没有内置微信 provider,我们得自己写一个。在项目里创建 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",
// 微信的授权地址(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()
},
},
// 把微信返回的用户信息转换成 NextAuth 的标准格式
profile(profile) {
return {
id: profile.openid,
name: profile.nickname,
email: null, // 微信不提供邮箱
image: profile.headimgurl,
}
},
options,
}
}
第三步:配置环境变量
在 .env.local 里加上微信配置:
WECHAT_CLIENT_ID=你的微信AppID
WECHAT_CLIENT_SECRET=你的微信AppSecret
第四步:在 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!,
}),
],
}
第五步:本地开发怎么测试?
这是个痛点。因为微信不允许 localhost 作为回调域,本地开发没法直接测试。
有两种解决办法:
方案1:用内网穿透工具
用 ngrok 或 cpolar 把你的本地服务暴露到公网:
# 安装 ngrok
brew install ngrok
# 启动内网穿透
ngrok http 3000
ngrok 会给你一个临时域名,比如 https://abc123.ngrok.io。把这个域名填到微信开放平台的授权回调域里,然后更新 .env.local 里的 NEXTAUTH_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,并在微信开放平台配置回调域为 dev.yourdomain.com。
但这个方案有个问题:微信要求回调域必须备案,所以 dev.yourdomain.com 还是过不了。最靠谱的还是方案1。
微信登录的特殊处理
微信用户没有邮箱,如果你的应用强依赖邮箱,需要额外处理:
async signIn({ user, account }) {
if (account?.provider === 'wechat') {
// 微信用户没有邮箱,可以让用户补填
// 或者用 openid 作为唯一标识存数据库
console.log("微信用户 openid:", user.id)
}
return true
}
安全最佳实践(避开常见坑)
配置完 OAuth 登录,还有一些安全细节要注意。这些坑我都踩过,血泪教训。
1. client_secret 绝对不能泄露
错误做法:
// ❌ 千万别这样写!
const clientSecret = "abc123def456" // 硬编码在代码里
如果你把 client_secret 写在前端代码或提交到 Git 仓库,别人拿到后就能冒充你的应用去获取用户信息。
正确做法:
- 用环境变量存储,
.env.local加入.gitignore - client_secret 只在后端使用(NextAuth.js 的 API route 是后端,所以没问题)
- 部署时用平台的环境变量管理(Vercel 的 Settings → Environment Variables)
2. state 参数的作用(防 CSRF 攻击)
OAuth 流程里有个 state 参数,它的作用是防止 CSRF 攻击。
攻击场景:黑客构造一个恶意链接,里面包含一个伪造的授权码,诱导你点击。如果你的应用没验证 state,就可能被骗去用这个假的授权码换 token。
好消息是,NextAuth.js 自动帮你处理了 state 验证,你不用额外写代码。
如果你自己实现 OAuth(不用 NextAuth.js),记得:
- 发起授权时生成一个随机 state,保存到 session 或 cookie
- 回调时检查返回的 state 是不是和你发出去的一致
- 不一致就拒绝
3. 回调地址白名单
在 OAuth 提供者(Google、GitHub、微信)后台,把所有可能的回调地址都配置好:
- 开发环境:
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 方式存储 session,token 保存在 HttpOnly Cookie 里。这是个很好的设计:
- HttpOnly:前端 JavaScript 无法读取这个 cookie,防止 XSS 攻击窃取 token
- Secure(生产环境):只通过 HTTPS 传输,防止中间人攻击
你要做的:
- 不要把 access_token 返回给前端(NextAuth.js 默认不返回,你也别主动返回)
- 如果需要持久化用户信息,在
signIncallback 里保存到数据库,session 里只存必要信息(user id、email)
5. 授权码的时效性
OAuth 的授权码(code)有效期很短(10分钟),只能用一次。
这是个安全设计:即使黑客截获了你的 code,等他反应过来去用的时候,code 可能已经过期或被你用掉了。
如果用户在授权页面停留太久(比如去泡了杯咖啡),回来时 code 可能已经过期。NextAuth.js 会自动处理这种情况,重新发起授权。
6. 生产环境检查清单
部署之前,检查一遍这些配置:
- 环境变量都设置了吗(NEXTAUTH_URL、NEXTAUTH_SECRET、各个 provider 的 client_id 和 client_secret)?
- NEXTAUTH_URL 改成生产域名了吗(不是 localhost)?
- OAuth 提供者后台配置了生产环境的回调地址吗?
- .env.local 在 .gitignore 里吗(确保 secret 不会被提交到 Git)?
- 生产环境的 NEXTAUTH_SECRET 是随机生成的吗(不要用开发环境的)?
总结
说了这么多,我们来快速总结一下。
OAuth 的本质其实就是”临时通行证”:你不需要把密码给第三方应用,只需要授权它去 OAuth 提供者那里拿一张有时效、有权限限制的通行证(access_token)。整个流程分两步:先用授权码(code)证明用户同意了,再用 code + client_secret 换真正的 token。
在 Next.js 里配置第三方登录,Google 最简单,是入门的最佳选择;GitHub 稍微复杂一点,需要注意 scope 配置和用户可能没有公开邮箱;微信最特殊,需要扫码、自定义 provider、回调域名备案,本地调试也比较麻烦。
安全方面,记住三个原则:
- client_secret 只在后端用,绝不泄露
- state 参数必须验证(NextAuth.js 帮你做了)
- 回调地址用白名单,不要通配符
如果你是第一次配置 OAuth,我建议从 Google 登录开始,跟着文章里的代码一步步来。配置成功后那种成就感,真的挺爽的。
遇到问题别慌,90% 的错误都是 redirect_uri 配置不对或者环境变量没设置。检查一遍,通常就能解决。
最后,推荐你去看看 NextAuth.js 官方文档,里面有更多高级用法(比如数据库存储 session、自定义登录页面、JWT 配置等)。OAuth 2.0 的标准规范(RFC 6749)也值得读一读,理解原理之后,再遇到问题就能举一反三了。
动手试试吧,祝你配置顺利!
Next.js OAuth 第三方登录配置完整流程
从零开始配置 Google、GitHub、微信三种第三方登录
⏱️ 预计耗时: 2 小时
- 1
步骤1: 安装和初始化 NextAuth.js
安装依赖:
• npm install next-auth
• 创建 app/api/auth/[...nextauth]/route.ts
基础配置:
• 设置 NEXTAUTH_URL(本地:http://localhost:3000,生产:实际域名)
• 设置 NEXTAUTH_SECRET(生成随机字符串)
• 配置基础 providers 数组 - 2
步骤2: 配置 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: 配置 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: 配置微信登录(可选)
步骤:
1. 注册微信开放平台账号(需要企业认证)
2. 创建网站应用,获取 AppID 和 AppSecret
3. 设置授权回调域名(需要备案)
4. 自定义 Provider(NextAuth 不内置微信)
5. 实现扫码登录流程
注意:微信登录较复杂,建议先完成 Google 和 GitHub 再尝试 - 5
步骤5: 创建登录页面和按钮
创建登录组件:
• 使用 signIn('google') 触发登录
• 使用 signOut() 退出登录
• 使用 useSession() 获取用户信息
• 使用 SessionProvider 包裹应用
示例:
<button onClick={() => signIn('google')}>
使用 Google 登录
</button> - 6
步骤6: 测试和调试
测试要点:
• 本地测试:确保回调地址是 http://localhost:3000
• 生产环境:确保回调地址与实际域名一致
• 检查环境变量是否正确设置
• 查看浏览器控制台和服务器日志
常见错误:
• redirect_uri_mismatch:回调地址不匹配
• invalid_client:Client ID 或 Secret 错误
• access_denied:用户拒绝授权
常见问题
OAuth 2.0 的工作原理是什么?
redirect_uri_mismatch 错误怎么解决?
解决方法:
1) 确保 OAuth 提供商后台配置的回调地址与代码中的完全一致(包括协议、域名、端口、路径)
2) 本地开发用 http://localhost:3000,生产环境用实际域名
3) 检查是否有多余的斜杠或参数
NextAuth.js 和手动实现 OAuth 有什么区别?
• 支持 50+ 提供商
• 自动处理授权流程、session 管理、CSRF 防护等
手动实现需要自己处理:
• 授权码交换
• token 存储
• state 验证等
代码量大且容易出错,建议使用 NextAuth.js。
如何获取用户的邮箱地址?
• Google:默认返回邮箱
• GitHub:需要在 scope 中包含 user:email,且用户必须设置邮箱为公开
• 微信:需要通过 unionid 查询
如果获取不到,可以在登录后让用户手动填写。
本地测试正常,部署到生产环境就报错?
检查:
1) 生产环境的 NEXTAUTH_URL 是否正确
2) OAuth 提供商后台的回调地址是否包含生产域名
3) 环境变量是否正确设置
4) 是否有防火墙或代理影响
可以同时支持多个登录方式吗?
OAuth 登录安全吗?
但需要注意:
1) client_secret 必须保密,只在服务端使用
2) 使用 state 参数防止 CSRF 攻击(NextAuth.js 自动处理)
3) 回调地址使用白名单,不要用通配符
4) 定期更新依赖包
18 分钟阅读 · 发布于: 2025年12月19日 · 修改于: 2026年1月22日
相关文章
Next.js 电商实战:购物车与 Stripe 支付完整实现指南
Next.js 电商实战:购物车与 Stripe 支付完整实现指南
Next.js 文件上传完整指南:S3/七牛云预签名URL直传实战
Next.js 文件上传完整指南:S3/七牛云预签名URL直传实战
Next.js 单元测试实战:Jest + React Testing Library 完整配置指南

评论
使用 GitHub 账号登录后即可评论