Next.js/Next-Auth/Apollo/GraphQL 设置
Posted
技术标签:
【中文标题】Next.js/Next-Auth/Apollo/GraphQL 设置【英文标题】:Next.js/Next-Auth/Apollo/GraphQL Setup 【发布时间】:2021-12-04 01:59:24 【问题描述】:我正在寻找有关如何处理使用 Apollo 和 GraphQL 访问 PostgreSQL 数据库的 next.js 前端的建议。我认为将前端和后端分开是有意义的,但我意识到存在权衡。 Next.js 和 NextAuth.js 在使用 Next.js API 功能时似乎设计得很好。
几个要求:
-
需要根据用户(公共、内部、管理员)限制数据。
使用 Google OAuth 登录
考虑到这一点,如果您希望后端了解用户的访问权限,NextAuth.js 会变得更加复杂。
但是,如果我的 apollo/graphql 后端是独立的,那么肯定会有以下好处:
-
如果需要,我可以更换前端,因此具有一定的灵活性
代码和依赖项可能比组合的前端/后端更简单
我目前面临的挑战是 NextAuth.js 在 Next.js 应用程序中工作,但我还没有弄清楚如何控制数据访问。到目前为止,我得到的最好的想法是某种将 NextAuth.js 和我的后端混合在一起的令牌管理。这似乎不是 NextAuth.js 的设计方式,所以我正在重新考虑整个架构并寻找建议。
谢谢!
我在这里找到了对类似问题的非常简短的讨论,但我很想听听其他人会如何处理这个问题。 How to forward user sessions in Next.js + Graphql decoupled architecture?
【问题讨论】:
我将尝试添加一个答案,但您是在使用 Google OAuth 作为通用社交登录还是作为组织登录?我实际上不确定它是否会有所作为。 谢谢,@Ben。大多数用户将成为 google 组织的一部分,但不是全部,因此它必须足够灵活以支持两者。我正在查看您的完整帖子,并在探索这些想法后会回来。非常感谢! 【参考方案1】:我将尽力给出一个相当通用的答案,使用 JWT 进行授权,但我将不得不做出一些假设,因为我对 Google OAuth 和相关的 Google 不是非常熟悉系统。
首先,也是最重要的一点,重要的是要明确身份验证或“你是谁”与授权或“你能做什么”之间的区别。
到目前为止,我的最佳想法是将 NextAuth.js 和我的后端混合在一起的某种令牌管理。这似乎不是 NextAuth.js 的设计方式,所以我正在重新考虑整个架构并寻找建议。
NextAuth 是一个身份验证库,是 NextAuth 创建的 JWT 的 doesn't support external validation,因此您不希望将 NextAuth 与后端混合使用是正确的。当有人登录 NextAuth 时,会创建一个 NextAuth 特定的 JWT(一个 ID 令牌),它将在 Client 和 Next Server 之间传递。它告诉你用户是谁,并证明他们已经登录。除非你使用数据库会话,我没有使用过,所以无法交谈。
需要额外的工作来实现授权,以便您拥有一个 JWT,该 JWT 还描述了用户拥有的访问权限,您可以将其传递给您的后端。
理想情况下,您将能够为此利用 Google OAuth,假设是这种情况,我会这样做:
对于架构
我对 GraphQL/Apollo 不是很熟悉,但那里的分离似乎很好。不过,重要的是要注意,不分离也可能没问题。任何方法都需要权衡取舍,因此您必须评估哪种方法最适合您的情况。 每当您调用后端时,您都会将 JWT 与调用一起作为Authorization
标头以Bearer <token>
的形式传递。
然后,您在后端验证每个传入呼叫的令牌,并根据需要允许呼叫继续(或不继续)。
This is the relevant info 我在 Apollo 文档中找到。
为了令牌
在您的 NextAuth 提供程序配置中,您可以在 jwt callback 中向 NextAuth JWT 添加信息。
理想情况下,您的 Google OAuth 也 为您提供 JWT(访问令牌)。这应该是 relatively easy to validate on the backend,这是您想要用于授权的东西。
您可以在用户首次登录时将此 Google OAuth JWT(访问令牌)内存储在 NextAuth JWT(id 令牌)中,然后在您创建之前在 Next.js 服务器上检索它调用 GraphQL 后端。看起来像这样:
// [...nextauth].js
const options =
// ... other configuration
callbacks:
jwt: async (token, user, account, profile, isNewUser) =>
const isSignIn = !!user
if (isSignIn)
token.b2c =
accessToken: account.accessToken,
refreshToken: account.refreshToken,
iat: profile.iat,
exp: profile.exp,
return Promise.resolve(token)
这是我使用的配置的简化示例。我的配置适用于 Azure AD B2C,但它与您正在寻找的一般流程相同。 You can see my full config here 显示了我用来根据需要处理刷新访问令牌的一些附加代码。
如果您没有可从 Google OAuth 流程中使用的东西,这会变得更加复杂,您必须构建一些自定义的东西。
【讨论】:
感谢@Ben,我在将其转换为 Google 提供程序格式方面取得了一些进展。但是,我目前正试图将令牌发送到我的后端。使用 Apollo-Client,我可以设置标头,但我不知道如何访问 JWT 令牌。 apollographql.com/docs/react/networking/authentication/#header 在被卡住之后,我研究了一个 Apollo 功能,您可以在其中发送凭据 cookie,但我希望我能弄清楚如何发送令牌标头。 apollographql.com/docs/react/networking/authentication/#cookie 我开始怀疑/探索将后端与前端结合起来。似乎 Next.js 就是为此而设计的,尤其是 Vercel。这将使身份验证更容易,并使共享代码更容易。在某些时候,它可能感觉像是一个单一的项目,但对我来说,也许这是正确的方法。 不确定阿波罗服务器身份验证标头/cookie 部分:/ IMO 组合可能没问题。总是有权衡,简单可能是您的情况的更好选择 - 我也会在我的回答中添加一个注释。以上是关于Next.js/Next-Auth/Apollo/GraphQL 设置的主要内容,如果未能解决你的问题,请参考以下文章