将 Next.js 更新为 React 18 中断了我使用 next-auth 的 API 调用

Update Next.js to React 18 breaks my API calls using next-auth

这很奇怪,但情况是这样的。

我正在使用 Next.js 和 Next-auth 包来处理身份验证。

我没有使用 Server-Side 渲染,它是一个管理区域,所以不需要 SSR,为了验证用户,我创建了一个 HOC 来包装除了“/sign-in”路线。

这个 HOC 所做的就是检查是否有 session 然后将“访问令牌”添加到 Axios 实例以便将它用于所有异步调用,如果没有 session,它将用户重定向到“sign-in”页面,如下所示...

const AllowAuthenticated = (Component: any) => {
  const AuthenticatedComponent = () => {
    const { data: session, status }: any = useSession();
    const router = useRouter();

    useEffect(() => {
      if (status !== "loading" && status === "unauthenticated") {
        axiosInstance.defaults.headers.common["Authorization"] = null;
        signOut({ redirect: false });
        router.push("/signin");
      } else if (session) {
        axiosInstance.defaults.headers.common["Authorization"] = `Bearer ${session.accessToken.accessToken}`;
      }
    }, [session, status]);

    if (status === "loading" || status === "unauthenticated") {
      return <LoadingSpinner />;
    } else {
      return <Component />;
    }
  };

  return AuthenticatedComponent;
};

export default AllowAuthenticated;

并且在 Axios 实例中,我正在检查响应是否为“401”,然后我注销用户并将他发送到“sign-in”屏幕,就像这样...

axiosInstance.interceptors.response.use(
  response => response,
  error => {
    const { status } = error.response;
    if (status === 401) {
      axiosInstance.defaults.headers.common["Authorization"] = null;
      signOut({ redirect: false });
      return Promise.reject(error);
    }
    return Promise.reject(error);
  },
);

非常简单的东西,在我决定升级我的项目以使用“react 18.1.0”和“react-dom 18.1.0”之前,它就像一个魅力,然后突然之间,我的API 来电未获得“授权”header 并且他们 return “401” 并且用户被注销 :(

如果我在设置 Auth headers 后立即尝试在 HOC 中进行 API 调用,那么我会从 session 中获取“令牌” ,但包装组件内的所有异步调度调用 return 401.

我忘了说,这个问题发生在页面刷新时,如果我在登录后没有刷新页面,一切正常,但是一旦我刷新页面,内部异步调度调用 return 401.

我更新了项目中的所有包,包括 Axios 和 next-auth,但没有帮助。

我最终不得不降级回“react 17.0.2”,然后一切又恢复正常了。

非常感谢任何帮助。

致那些可能遇到同样问题的人。

我设法通过不包括将令牌添加到 HOC 中的“授权”header 的逻辑来解决这个问题,相反,我使用了 @kamal-choudhary 在 post 在 Github 上谈论如何使用 next-auth.

向每个 axios 调用添加“JWT”

在@jaketoolson 的帮助下 Github post,他能够将令牌附加到每个 "Axios" 调用。

解决方案基本上是创建一个 Axios 实例并添加一个拦截器,就像我在上面所做的那样,但不仅针对 response,还针对 request

您将为每个请求添加一个拦截器并检查是否有 session,然后将 JWT 附加到 Authorization header

成功解决了我的问题,现在 next-authreact 18 配合得很好。

这是他使用的代码...

import axios from 'axios';
import { getSession } from 'next-auth/react';

const baseURL = process.env.SOME_API_URL || 'http://localhost:1337';

const ApiClient = () => {
  const defaultOptions = {
    baseURL,
  };

  const instance = axios.create(defaultOptions);

  instance.interceptors.request.use(async (request) => {
    const session = await getSession();
    if (session) {
      request.headers.Authorization = `Bearer ${session.jwt}`;
    }
    return request;
  });

  instance.interceptors.response.use(
    (response) => {
      return response;
    },
    (error) => {
      console.log(`error`, error);
    },
  );

  return instance;
};

export default ApiClient();

如果对您有用,请不要忘记给他们点个赞...

https://github.com/nextauthjs/next-auth/discussions/3550#discussioncomment-1993281

https://github.com/nextauthjs/next-auth/discussions/3550#discussioncomment-1898233