Apollo 客户端 + Next.js - 将授权令牌添加到客户端请求

cod*_*ire 6 authorization apollo server-side-rendering react-apollo next.js

目标

我想Authorization用访问令牌填充我的标头。我想将该访问令牌存储在 Apollo 缓存中,因为Auth0明确声明不要将访问令牌存储在本地存储中(我不知道为什么Apollo 客户端文档似乎认为这是可以的)。

如果做不到这一点,我想安全地存储我的访问令牌,并能够将其添加到 Apollo 服务器的每个 Apollo 客户端请求中。

const apolloClient = withApollo(({ctx, headers, initialState}) => {
  const cache = new InMemoryCache();

  // Code here to access local cache.

  return new ApolloClient({

    cache,
    link: new HttpLink({
      uri: <apollo server endpoint>,
      headers: {
        Authorization: `Bearer ${accessToken}`,
        'Access-Control-Allow-Origin': 'http://localhost:3000/',
        ...headers
      },
      credentials: 'include'
    }),
    typeDefs,
    resolvers
  })
})

class MyApp extends App {
  render() {
    const { Component, pageProps, apollo } = this.props;


    return (
      <ApolloProvider client={apollo}>
        <Component {...pageProps} />
      </ApolloProvider>
    );
  }
}

export default apolloClient(MyApp);
Run Code Online (Sandbox Code Playgroud)

尝试过

  • 我尝试localStorage从该withApollo函数内部访问,但它是 SSR 的,所以我无法访问它。我打算使用localStorage设置一个布尔值来签入withApollo函数,这样它就会知道重定向后访问令牌已添加到 apollo 缓存中。
  • 我尝试仅使用带有存储布尔值的密钥的缓存来检查用户是否已登录,该登录是在访问令牌所在的同一函数中设置的。如果这是真的,我将访问访问令牌密钥并将其添加到Authorization标头中。但我在设置初始状态覆盖登录功能中的缓存集时遇到了问题。

其他想法

  • 我认为我可以在参数中传递访问令牌ctx,但我对 Next.js 不够熟悉,无法确定这是否是有效的方法。

  • 我以为我可以将 propswithApollo从组件传递给函数,但这似乎不可能。

问题

  • 存储访问密钥以便在每次请求时将其添加到 Apollo 客户端的最佳方式是什么?
  • 我注意到有些人正在使用fetchPolyfill,这适合这种情况吗?如果是这样,那将如何运作?
  • HOC如何withApollo工作以及为什么需要它与 Next.js 一起使用?我已经阅读了这背后的一些代码,但我并没有从根本上理解为什么需要它。

cod*_*ire 6

我能够找到我的问题的解决方案。我只是没有完全理解 Apollo 客户端以及如何使用所有必需的包。

解决方案

我用的setContext是图书馆的apollo-link-context。它是 Apollo Client 提供的库集的一部分link,用于在 graphql 操作开始后自定义网络请求。我在函数中设置了标题setContext。就像这样:

const authLink = setContext((_, { headers }) => {
  // It is also possible to use the local storage method in here.
  const data = cache.readQuery({
    query: ACCESS_TOKEN
  });

  return {
    headers: {
      ...headers,
      authorization: accessToken ? `Bearer ${data.accessToken}` : ""
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

以下是withApollo函数之外的内容。

const httpLink = new HttpLink({
  uri: '<server uri>',
});
Run Code Online (Sandbox Code Playgroud)

以下是withApollo函数内部。

return new ApolloClient({
    cache,
    link: authLink.concat(httpLink),
    typeDefs,
    resolvers
  })
Run Code Online (Sandbox Code Playgroud)

有关如何操作的文档setContext位于此处,有关“apollo-link-context”的文档位于此处