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

joc*_*ers 5 node.js jwt graphql react-native apollo-client

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

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

GraphQL 突变

mutation UpdateTokens($refreshToken: String!, $refreshTokenId: String!) 
 {
    updateTokens(refreshToken: $refreshToken, refreshTokenId: $refreshTokenId) {
      user {
        name
        phone
      }
      accessToken
      refreshToken
    }
  }
Run Code Online (Sandbox Code Playgroud)

应用程序.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
Run Code Online (Sandbox Code Playgroud)

Gre*_*zik 5

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

我认为您不需要担心使用您的令牌手动或以其他方式更新您的 Apollo 缓存,至少有几个原因。首先,考虑到您存储的内容的准敏感性质,最好遵循更安全的存储解决方案,在这种情况下可能是钥匙串。此外,为应用程序中的令牌提供单一的真实来源可以保持整洁。

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