如何使用Apollo和React Native在每个graphql请求之前实现自动jwt令牌刷​​新?

时间:2019-08-07 11:11:28

标签: node.js react-native jwt graphql apollo-client

我想在 React Native 应用中使用 Apollo 中间件对 GraphQL 的每次请求之前实现自动刷新jwt令牌。每次用户登录后,他都会获得两个令牌:访问和刷新。访问令牌,它是用于授权头中30-60分钟的短令牌。刷新令牌是用于确认刷新令牌graphql突变的60天的较长时间。 我的流程:

  1. 用户登录并获得2个令牌->使用 Appollo setContext将访问令牌放入授权标头。
  2. 用户向 GraphQL 发出请求->检查客户端上accessToken的到期时间: ->如果未过期->确认请求 ->如果已过期->调用 GraphQL refreshToken突变->获取新令牌->确认请求。 为了将令牌保留在客户端,我使用了 KeyChain 存储。您能告诉我吗,我也应该使用 Apollo 缓存来保留令牌吗?我应该为令牌写 Apollo 状态吗?以及如何实现流程?

GraphQL突变

mutation UpdateTokens($refreshToken: String!, $refreshTokenId: String!) 
 {
    updateTokens(refreshToken: $refreshToken, refreshTokenId: $refreshTokenId) {
      user {
        name
        phone
      }
      accessToken
      refreshToken
    }
  }

App.js

import React from 'react'
import { ApolloClient } from 'apollo-client'
import { ApolloLink } from 'apollo-link'
import { ApolloProvider } from 'react-apollo'
import { ApolloProvider as ApolloHooksProvider } from 'react-apollo-hooks'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { setContext } from 'apollo-link-context'
import * as Keychain from 'react-native-keychain'
import AppNavigator from './AppNavigator'

const httpLink = createHttpLink({
  uri: 'http://localhost:4000'
})

const cache = new InMemoryCache()

const authLink = setContext(async (req, { headers, ...context }) => {
  const tokens = await Keychain.getGenericPassword()
  const accessToken = tokens.username
  return {
    headers: {
      ...headers,
      authorization: accessToken ? `Bearer ${accessToken}` : ''
    },
    ...context
  }
})

const client = new ApolloClient({
  link: ApolloLink.from([authLink, httpLink]),
  cache,
  connectToDevTools: true
})

const App = () => {
  return (
    <ApolloProvider client={client}>
      <ApolloHooksProvider client={client}>
        <AppNavigator />
      </ApolloHooksProvider>
    </ApolloProvider>
  )
}

export default App

1 个答案:

答案 0 :(得分:2)

老实说,我认为您走在正确的道路上-在阅读您所需要的功能时,我想到了apollo-link-context,很高兴看到您采用了这种方法。最近,我们不得不在react-native应用程序中实现类似的功能,这需要在自定义标头中附加与身份验证相关的数据。要检索此数据,我们需要发出异步请求,尽管我们的请求是通过网络连接到第三方服务的。与您一样,我们都是在setContext中从客户端完成此操作的。这很好。

出于某些原因,我认为您无需手动或用其他方式更新令牌来更新Apollo缓存。首先,考虑到存储内容的准敏感性质,最好的做法是采用更安全的存储解决方案,在这种情况下,这很可能是钥匙串。此外,在您的应用程序中只有一个真实的令牌来源可以使事情保持清洁。

假设您不想将此数据写入缓存,我将仔细检查Apollo客户端是否没有自动这样做。例如,如果您出于某种原因先前查询了令牌数据,则Apollo可能会在收到突变有效负载后自动更新缓存。只是要注意的事情。