当尝试访问后端(Apollo GraphQL)并由于令牌已过期或无效而返回401时,清除NextAuth.js会话的最佳方法是什么?
我考虑了errorLink
and signout
,但据我所知signout
,不能在服务器端使用getServerSideProps
,只能在客户端使用。
建议这样做的方法是什么?还有其他方法可以实现中间件来解决这种情况吗?
这将是errorLink
我正在尝试实现的concepto的证明,其中包含了代码,if
但是我不能使用它,signOut()
因为它仅在客户端可用。
const errorLink = onError(({ graphQLErrors }) => {
if (graphQLErrors?.[0]?.message === 'Unauthenticated.') {
// signOut();
}
});
function createApolloClient(session) {
return new ApolloClient({
cache: new InMemoryCache(),
ssrMode: typeof window === 'undefined',
link: from([
errorLink,
createUploadLink({
uri: GRAPHQL_URI,
credentials: 'same-origin',
headers: { Authorization: session?.accessToken ? `Bearer ${session.accessToken}` : '' },
}),
]),
});
}
谢谢
正如Noah和Yog告诉你的那样,没有办法在服务器端执行此操作,因为signOut
必须清除状态客户端。所以这就是我要做的:
function createApolloClient(session) {
return new ApolloClient({
cache: new InMemoryCache(),
ssrMode: typeof window === 'undefined',
link: from([
createUploadLink({
uri: GRAPHQL_URI,
credentials: 'same-origin',
headers: { Authorization: session?.accessToken ? `Bearer ${session.accessToken}` : '' },
}),
]),
});
}
然后,在你的getServerSiderProps
:
export const fetchServerSideProps = (
initializeApollo: (context: SessionBase | null) => ApolloClient<NormalizedCacheObject>
): GetServerSideProps => async (context) => {
const session = await getSession(context);
const apolloClient = initializeApollo(session);
try {
// Fetch anything from GraphQL here
return {
props: {
// add your required page props here
session,
},
};
} catch {
// Token invalid or expired error (401) caught here, so let's handle this client-side.
return { props: { session: null } };
}
};
最后,你的页面如下所示:
const withAuth = <P extends { session: Session | null }>(Page: NextPage<P>) => (props: P): JSX.Element | null => {
if (!props.session) {
// Clear session and redirect to login
signOut({ callbackUrl: '/login' });
return null;
}
return <Page {...props} />;
};
const Page: NextPage<P> = (props) => (
<p>This should be shown ONLY if the user is logged in</p>
);
export default withAuth(LoggedInPage);
如果不能在服务器端完成,我想这将是更好的流程,对吗?