Как настроить клиент Apollo с токеном JWT в Next.JS приложение, использующее серверную часть Hasura?

#jwt #next.js #apollo-client #hasura

Вопрос:

У меня возникли проблемы с настройкой клиента Apollo с помощью токена JWT на Next.JS проект, использующий базу данных Hasura GraphQL.

Странно то, что иногда данные загружаются; иногда запрос выдает ошибку (см. Внизу).

Я создал своего клиента Apollo таким образом:

 import { ApolloClient, InMemoryCache } from "@apollo/client";  const client = new ApolloClient({  uri: process.env.NEXT_PUBLIC_HASURA_GRAPHQL_URL,  cache: new InMemoryCache(),  fetchOptions: {  mode: 'no-cors',  }, });  export default client;  

В pages/_app.js, Я звоню клиенту в качестве поддержки ApolloProvider:

 return (  lt;UserContext.Provider value={[user, setUser]}gt;  lt;ApolloProvider client={client}gt;  lt;Component {...pageProps} /gt;  lt;/ApolloProvidergt;  lt;/UserContext.Providergt;  );  

Когда пользователи входят на домашнюю страницу, вызывается следующая функция API, сохраненная в pages/api/login:

 import {Magic} from '@magic-sdk/admin' import CookieService from '../../lib/cookie' import jwt from 'jsonwebtoken';   let magic = new Magic(process.env.MAGIC_SECRET_KEY)  export default async (req, res) =gt; {  if (req.method !== 'POST') return res.status(405).end()    // exchange the DID from Magic for some user data  const did = magic.utils.parseAuthorizationHeader(req.headers.authorization)  const user = await magic.users.getMetadataByToken(did);   // create jwt token  let token = jwt.sign(  {  ...user,  'https://hasura.io/jwt/claims': {  'x-hasura-allowed-roles': ['user'],  'x-hasura-default-role': 'user',  'x-hasura-user-id': `${user.issuer}`,  },  exp: Math.floor(Date.now() / 1000)   60 * 60 * 24 * process.env.SESSION_LENGTH_IN_DAYS,  },  process.env.JWT_SECRET  );   // Author a couple of cookies to persist a users session  CookieService.setTokenCookie(res, token)    res.json(user);   res.end(); }  

This is the CookieService.setTokenCookie function:

 function setTokenCookie(res, token) {  res.setHeader("Set-Cookie", [  createCookie(TOKEN_NAME, token),  createCookie("authed", true, { httpOnly: false }),  ]) }  

I created a hook to access the JWT token:

 import useSWR from "swr";  const fetchUser = url =gt;  fetch(url)  .then(r =gt; r.json())  .then(data =gt; {  return { user: data?.user || null }; });  export function useUser() {  const { data, error } = useSWR('/api/user', fetchUser);  return !data amp;amp; !error ? { loading: true } : data amp;amp; data?.user; }  

In various pages in the app, I call useUser and use the useQuery hook to query the database:

 const user = useUser();  const { data, loading, error } = useQuery(GetData,   {  context: {  headers: {  Authorization : `Bearer ${token}`  }  },  } );  

With this implementation, I am sometimes able to receive data from the backend but oftentimes receive the following error:

 Error: Could not verify JWT: JWSError (CompactDecodeError Invalid number of parts: Expected 3 parts; got 1)  at new ApolloError (index.js?3ca0:31)  at QueryData.getExecuteResult (QueryData.js?74a3:213)  at QueryData.execute (QueryData.js?74a3:44)  at eval (useBaseQuery.js?b9a7:32)  at useDeepMemo (useDeepMemo.js?31e9:6)  at useBaseQuery (useBaseQuery.js?b9a7:32)  at useQuery (useQuery.js?f933:3)  at Offerings (index.js?3ad2:26)  at renderWithHooks (react-dom.development.js?61bb:14985)  at updateFunctionComponent (react-dom.development.js?61bb:17356)  at beginWork (react-dom.development.js?61bb:19063)  at beginWork$1 (react-dom.development.js?61bb:23940)  at performUnitOfWork (react-dom.development.js?61bb:22776)  at workLoopSync (react-dom.development.js?61bb:22707)  at renderRootSync (react-dom.development.js?61bb:22670)  at performSyncWorkOnRoot (react-dom.development.js?61bb:22293)  at eval (react-dom.development.js?61bb:11327)  at unstable_runWithPriority (scheduler.development.js?3069:468)  at runWithPriority$1 (react-dom.development.js?61bb:11276)  at flushSyncCallbackQueueImpl (react-dom.development.js?61bb:11322)  at flushSyncCallbackQueue (react-dom.development.js?61bb:11309)  at scheduleUpdateOnFiber (react-dom.development.js?61bb:21893)  at dispatchAction (react-dom.development.js?61bb:16139)  at eval (useBaseQuery.js?b9a7:18)  

Дайте мне знать, если у вас есть какие-либо советы о том, как устранить эту ошибку!