jwt - 如何使用 Hasura 后端在 Next.JS 应用程序中使用 JWT 令牌配置 Apollo 客户端?
问题描述
我在使用 Hasura GraphQL 数据库的 Next.JS 项目中使用 JWT 令牌配置 Apollo 客户端时遇到问题。
奇怪的是,有时数据会加载;有时,查询会出错(见底部)。
我这样设置我的 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 中,我调用 client 作为 ApolloProvider 的道具:
return (
<UserContext.Provider value={[user, setUser]}>
<ApolloProvider client={client}>
<Component {...pageProps} />
</ApolloProvider>
</UserContext.Provider>
);
当用户登录主页时,会调用以下 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) => {
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();
}
这是 CookieService.setTokenCookie 函数:
function setTokenCookie(res, token) {
res.setHeader("Set-Cookie", [
createCookie(TOKEN_NAME, token),
createCookie("authed", true, { httpOnly: false }),
])
}
我创建了一个挂钩来访问 JWT 令牌:
import useSWR from "swr";
const fetchUser = url =>
fetch(url)
.then(r => r.json())
.then(data => {
return { user: data?.user || null };
});
export function useUser() {
const { data, error } = useSWR('/api/user', fetchUser);
return !data && !error ? { loading: true } : data && data?.user;
}
在应用程序的各个页面中,我调用 useUser 并使用 useQuery 挂钩来查询数据库:
const user = useUser();
const { data, loading, error } = useQuery(GetData,
{
context: {
headers: {
Authorization : `Bearer ${token}`
}
},
}
);
通过这种实现,我有时能够从后端接收数据,但经常会收到以下错误:
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)
如果您对如何解决此错误有任何提示,请告诉我!
解决方案
推荐阅读
- php - 插入数据后如何更新和删除
- tuples - 如何为 OpenAPI 中的每个索引(即元组)定义一个带有具体项目定义的 JSON 数组?
- api - Angular 6 中订阅的错误处理程序未从 ASP.Net Core API 获取错误消息
- c# - Xamarin.iOS NSUnknownKeyException 原因:[ setValue:forUndefinedKey:]:此类与键 staticDataSource 的键值编码不兼容
- javascript - 向下滚动或打开链接
- java - IllegalStateException: play() 在未初始化的 AudioTrack 上调用
- java - OnetoOne 关系案例中的唯一行。如何防止重复?
- playframework - 如何为 sbt 中提供的传递依赖提供版本?
- php - Codeigniter LEFT JOIN 未按预期工作
- function - haskell 中的函数 (.).(.)