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 设置的主要内容,如果未能解决你的问题,请参考以下文章