next.js 和下一个身份验证刷新令牌

问题描述 投票:0回答:1

我对刷新令牌在 NextAuth 中的工作原理有点困惑。

我遵循了他们的文档,但在回调中,他们在与客户端共享的会话中包含刷新令牌。这意味着会话对象(可在浏览器中访问)包含刷新令牌,这似乎不安全。

情况是这样的:使用NextAuth时,登录发生在服务器端。我使用凭据提供程序登录 Node.js 后端,该后端生成两个安全的 httpOnly cookie:

refreshToken
accessToken

现在,我的问题是:我应该如何在 NextAuth 回调中处理这个问题?具体来说,如何检查访问令牌是否已过期并请求新的服务器端而不在与客户端共享的会话中包含刷新令牌?

对于上下文,所有其他 API 调用都是在客户端进行的,并且我的 Next.js 受保护的路由在服务器端进行验证。我确实将访问令牌保存在客户端会话中,因为 API 调用需要它,但我想避免将刷新令牌暴露给客户端。

next.js next-auth
1个回答
0
投票

要解决在 NextAuth 中安全管理刷新令牌的问题,您可以使用 next-refresh-token(https://www.npmjs.com/package/next-refresh-token) 包。该包提供了一种安全有效的方法来处理刷新令牌,确保它们存储在服务器端的 httpOnly cookie 中,而不是将它们暴露给客户端。

安装

首先,使用以下命令安装软件包:

npm install next-refresh-token

实施

下面是如何将

next-refresh-token
集成到 Next.js 项目中以安全管理刷新令牌的分步实施。

1.使用
next-refresh-token

配置 NextAuth

next-refresh-token
包增强了 NextAuth,允许您安全地处理刷新令牌,而无需在客户端公开它们。按如下方式更新您的 NextAuth API 路由:

// pages/api/auth/[...nextauth].js
import NextAuth from "next-auth";
import { withRefreshToken } from "next-refresh-token";

export default withRefreshToken(
  NextAuth({
    providers: [
      {
        id: "credentials",
        name: "Credentials",
        authorize: async (credentials) => {
          const user = await loginToYourBackend(credentials); // Custom login logic
          if (user) {
            return user;
          } else {
            return null;
          }
        },
      },
    ],
    callbacks: {
      async jwt({ token, user }) {
        if (user) {
          token.accessToken = user.accessToken;
          token.refreshToken = user.refreshToken;
        }
        return token;
      },
      async session({ session, token }) {
        session.accessToken = token.accessToken;
        return session;
      },
    },
    secret: process.env.NEXTAUTH_SECRET, // Set a secure secret
  }),
  {
    refreshTokenEndpoint: "/api/auth/refresh", // Endpoint to handle token refreshes
    accessTokenExpiry: 60 * 15, // Access token expiry time in seconds (e.g., 15 minutes)
  }
);

2.创建刷新令牌 API 端点

刷新端点用于使用存储在 httpOnly cookie 中的刷新令牌安全地生成新的访问令牌。

// pages/api/auth/refresh.js
import { refreshTokenHandler } from "next-refresh-token";

export default refreshTokenHandler({
  async refresh(refreshToken) {
    // Replace this with your backend API call to get a new access token
    const response = await fetch("https://your-backend.com/api/refresh-token", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ refreshToken }),
    });

    if (response.ok) {
      const data = await response.json();
      return {
        accessToken: data.accessToken, // Return the new access token
        refreshToken: data.refreshToken, // Return a new refresh token if applicable
      };
    } else {
      throw new Error("Failed to refresh token");
    }
  },
});

3.自动刷新客户端上的访问令牌

为了确保您的客户端 API 调用始终具有有效的访问令牌,您可以使用

getSession
中的
next-auth/react
检查会话并在需要时刷新令牌。

import { getSession } from "next-auth/react";

async function fetchData() {
  const session = await getSession(); // Get the session object with the access token
  const accessToken = session?.accessToken;

  const response = await fetch("/api/protected-endpoint", {
    headers: {
      Authorization: `Bearer ${accessToken}`,
    },
  });

  if (!response.ok) {
    throw new Error("Failed to fetch data");
  }

  return response.json();
}

4.验证令牌的中间件

如果您的应用严重依赖受保护的路由,您可以创建中间件来确保所有 API 请求都经过身份验证并且访问令牌有效。

// middleware.js
import { withAuthMiddleware } from "next-refresh-token";

export default withAuthMiddleware({
  tokenRefreshEndpoint: "/api/auth/refresh",
});

使用的好处
next-refresh-token

  1. 增强安全性:刷新令牌存储在httpOnly cookie中,确保它们不会暴露给客户端。
  2. 无缝令牌刷新:访问令牌过期时自动刷新。
  3. 可定制性:轻松配置刷新令牌端点、访问令牌过期和其他行为。
  4. 易于使用:可作为
    next-auth
    的即插即用解决方案。

最后的笔记

通过使用

next-refresh-token
包,您可以安全地处理刷新令牌,而无需将它们暴露给客户端。这种方法增强了安全性并简化了令牌生命周期管理,使其成为生产就绪应用程序的绝佳选择。

更多详情请参考官方文档:next-refresh-token

© www.soinside.com 2019 - 2024. All rights reserved.