Использование refre sh токена в GraphQL на стороне клиента, когда токен истек - PullRequest
1 голос
/ 10 марта 2020

Сценарий:

  1. Веб-приложение открыто, но токен истек.
  2. Затем пользователь выполняет какое-то действие, которое делает запрос API.
  3. GraphQL возвращает Error: GraphQL error: unauthorized.
  4. Приложение не отвечает из-за ошибки. Плохой пользовательский опыт.
  5. onError из apollo-link-error метод отлавливает ошибку, и из этого я могу вызвать refreshToken() (требуется jwt с истекшим сроком действия).
  6. Новый токен генерируется и сохраняется для использования.
  7. Следующее действие пользователя будет go выполнено как обычно.

В настоящее время это мой код:

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    refreshToken();
  }
});

const link = ApolloLink.from([errorLink, terminatingLink]);

Как Можем ли мы улучшить этот поток, чтобы токен обновлялся, когда пользователь делает запрос без получения ошибки? Что-то вроде запроса «удерживается», если он вызывает ошибку, то после обновления токена он обрабатывается. Но я не уверен, как это сделать.

Или есть какой-то другой способ улучшить этот поток?

1 Ответ

1 голос
/ 10 марта 2020

Вы можете создать ссылку, которую можно запустить до того, как операция будет выполнена через вашу завершающую ссылку. Вы можете создать свою собственную ссылку без сохранения состояния , но вы также можете обойтись с помощью setContext , который можно использовать для установки заголовков ваших запросов, пока мы на нем.

Поскольку вы используете JWT, вы можете декодировать его на стороне клиента , чтобы извлечь значение срока действия и использовать его, чтобы определить, нужно ли обновить sh токен до запрос отправляется на сервер. Если вы не использовали JWT, но сервер вернул время истечения с токеном, применима та же стратегия.

const contextLink = setContext(async () => {
  const { exp } = jwtDecode(jwt)
  // subtracts a minute to account for latency
  const expirationTime = (exp * 1000) - 60000
  if (Date.now() >= expirationTime) {
    await refreshToken()
  }
  return {
    // you can set your headers directly here based on the new token
    headers: {
      ...
    }
  }
})
...