NextJS 13中Next-Auth结合Strapi实现Google登录的用户持久化与令牌获取问题
NextJS 13 + NextAuth + Strapi Google 认证解决方案
前置准备
先在 Strapi 端完成 Google 认证配置:
- 启用 Strapi 的「Users & Permissions」插件
- 在插件设置中开启 Google 认证,填入和 NextAuth 一致的 Google Client ID、Client Secret
- Google 控制台添加 NextAuth 回调地址:
http://localhost:3000/api/auth/callback/google(生产环境替换为你的域名)
修正后的 NextAuth 配置代码
app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth'; import GoogleProvider from "next-auth/providers/google"; import type { NextAuthOptions, Session, JWT } from 'next-auth'; const authOptions: NextAuthOptions = { providers: [ GoogleProvider({ clientId: process.env.GOOGLE_CLIENT_ID as string, clientSecret: process.env.GOOGLE_CLIENT_SECRET as string, authorization: { params: { scope: 'openid email profile' } } }) ], callbacks: { async jwt({ token, user, account }): Promise<JWT> { if (user && account) { try { // 调用 Strapi 的 Google OAuth 回调,交换 Strapi JWT const strapiResponse = await fetch( `${process.env.NEXT_PUBLIC_API_URL}/api/auth/google/callback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ access_token: account.accessToken }) } ); if (!strapiResponse.ok) throw new Error('Strapi 认证失败'); const strapiData = await strapiResponse.json(); // 存入 Strapi 令牌和用户 ID 到 NextAuth Token token.strapiJwt = strapiData.jwt; token.strapiUserId = strapiData.user.id; token.email = user.email; token.name = user.name; token.picture = user.image; } catch (err) { console.error('Strapi OAuth 回调错误:', err); throw err; } } return token; }, async session({ session, token }): Promise<Session> { if (session.user) { // 把 Strapi 令牌同步到前端 Session session.user.strapiJwt = token.strapiJwt as string; session.user.strapiUserId = token.strapiUserId as string; session.user.email = token.email as string; session.user.name = token.name as string; session.user.image = token.picture as string; } return session; }, }, secret: process.env.NEXTAUTH_SECRET as string, pages: { signIn: '/auth/signin' } }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
核心问题解答
1. 如何将用户信息持久化到 Strapi 数据库?
通过调用 Strapi 官方提供的 /api/auth/google/callback 端点,Strapi 的「Users & Permissions」插件会自动处理:
- 如果 Google 账号对应的邮箱已在 Strapi 存在,直接关联该账号
- 如果不存在,自动创建新用户并同步 Google 返回的邮箱、姓名、头像等信息
无需手动编写数据库操作代码,插件已封装好完整逻辑。
2. 如何获取 Strapi 访问令牌并用于 API 请求?
- 在
jwt回调中提取 Strapi 返回的jwt字段,存入 NextAuth 的 Token 中 - 通过
session回调将令牌同步到前端可用的 Session 对象 - 后续请求 Strapi 受保护 API 时,在请求头中携带令牌:
import { getServerSession } from 'next-auth/next'; import authOptions from './api/auth/[...nextauth]/route'; async function fetchProtectedStrapiData() { const session = await getServerSession(authOptions); if (!session?.user?.strapiJwt) throw new Error('用户未认证'); const response = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/protected-endpoint`, { headers: { 'Authorization': `Bearer ${session.user.strapiJwt}` } }); return response.json(); }
额外配置(TypeScript 类型扩展)
在项目根目录创建 types/next-auth.d.ts,扩展 Session 和 JWT 类型:
import type { DefaultSession, DefaultJWT } from 'next-auth'; declare module 'next-auth' { interface Session extends DefaultSession { user: DefaultSession['user'] & { strapiJwt: string; strapiUserId: string; }; } interface JWT extends DefaultJWT { strapiJwt: string; strapiUserId: string; } }
内容的提问来源于stack exchange,提问作者japheth
相关产品推荐
相关产品推荐

