将 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-auth
与 react 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
这很奇怪,但情况是这样的。
我正在使用 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-auth
与 react 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