下一步。js/Next-Auth/Apollo/GraphQL 设置

Next.js/Next-Auth/Apollo/GraphQL Setup

我正在寻找有关如何使用 Apollo 和 GraphQL 访问 PostgreSQL 数据库的 next.js 前端的建议。我认为将前端和后端分开是有意义的,但我意识到需要权衡取舍。 Next.js 和 NextAuth.js 似乎设计为在使用 Next.js API 功能时运行良好。

一些要求:

  1. 需要根据用户(public、内部、管理员)限制数据。
  2. 使用 Google OAuth 登录

考虑到这一点,如果您希望后端了解用户的访问权限,NextAuth.js 会变得更加复杂。

但是,如果我的 apollo/graphql 后端是独立的,那么肯定有以下好处:

  1. 如果需要,我可以换掉前端,所以有一定的灵活性
  2. 代码和依赖项可能比组合起来更简单 front/back end

我目前的挑战是我已经在 Next.js 应用程序中使用了 NextAuth.js,但我还没有弄清楚如何控制数据访问。到目前为止我得到的最好的想法是某种混合 NextAuth.js 和我的后端的令牌管理。这似乎不是 NextAuth.js 的设计方式,所以我正在重新考虑整个架构并寻求建议。

谢谢!

我在这里找到了对类似问题的非常简短的讨论,但我很想听听其他人是如何处理这个问题的。

我将尽我所能给出一个相当通用的答案,使用 JWT 进行授权,但我将不得不做出一些假设,因为我对 Google OAuth 及相关 Google 系统。

首先,也是最重要的一点,澄清身份验证(或“您是谁”)与授权(或“您可以做什么”)之间的区别很重要。

The best idea I've got so far is some sort of token management that mixes NextAuth.js and my back end. That doesn't seem to be the way NextAuth.js is designed though so I'm rethinking the whole architecture and looking for suggestions.

NextAuth 是一个身份验证库,并且是 NextAuth-created JWT 的 doesn't support external validation,因此您不想将 NextAuth 与您的后端混合使用是对的。当有人登录 NextAuth 时,会创建一个 NextAuth-specific JWT(一个 ID 令牌),它将在客户端和下一个服务器之间传递。它告诉您用户是谁,并证明他们已经登录。除非您使用的是数据库会话,我没有使用过,所以无法与之交谈。

实施授权需要额外的工作,以便您拥有一个 JWT,该 JWT 还描述了用户拥有的访问权限,您可以将其传递给后端。

理想情况下,您将能够为此利用 Google OAuth,假设是这种情况,这就是我要做的:

对于架构

  • 我对GraphQL/Apollo不是很熟悉,但那里的分离似乎很好。但需要注意的是,不分离也可能很好。任何方法都会有所取舍,因此您必须评估哪种方法最适合您的情况。
  • 每当您调用后端时,您都会将 JWT 作为 Authorization header 的调用以 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 流程中没有可用的东西,这会变得更加复杂,您必须构建一些自定义的东西。