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

时间:2019-09-24 08:35:37

标签: authorization apollo next.js react-apollo server-side-rendering

目标

我想用访问令牌填充Authorization标头。我想将该访问令牌存储在Apollo缓存中,因为Auth0明确声明不要在本地存储中存储访问令牌(我不知道为什么Apollo Client docs似乎认为还可以)。

否则,我想安全地存储访问令牌,并能够将其添加到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);

尝试

  • 我尝试从localStorage函数中访问withApollo,但是它已进行SSR,所以我无法访问它。我打算使用localStorage来设置布尔值以检入withApollo函数,这样它将知道在重定向之后访问令牌已添加到阿波罗缓存中。
  • 我尝试仅将高速缓存与存储布尔值的键一起使用,以检查用户是否已登录,并且该键设置为与访问令牌相同的功能。如果是这样,我将访问访问令牌密钥并将其添加到Authorization标头中。但是我在设置初始状态而不是登录功能中设置的缓存方面遇到了问题。

其他想法

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

  • 我以为我可以从组件中将道具传递给withApollo函数,但这似乎是不可能的。

问题

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

1 个答案:

答案 0 :(得分:1)

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

解决方案

我使用了setContext库中的apollo-link-context。它是link库集合的一部分,Apollo Client提供了一组库,可在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}` : "",
      'Access-Control-Allow-Origin': 'http://localhost:3000/'
    }
  }
});

以下内容不在withApollo函数之内。

const httpLink = new HttpLink({
  uri: '<server uri>',
});

下面是withApollo函数的内部。

return new ApolloClient({
    cache,
    link: authLink.concat(httpLink),
    typeDefs,
    resolvers
  })

setContexthere的文档,而`apollo-link-context'的文档是here