如何使用 Apollo 和 GraphQL 刷新 JWT 令牌 [英] How to refresh JWT token using Apollo and GraphQL

查看:28
本文介绍了如何使用 Apollo 和 GraphQL 刷新 JWT 令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我们正在使用 Apollo 和 GraphQL 创建一个 React-Native 应用程序.我正在使用基于 JWT 的身份验证(当用户同时登录 activeTokenrefreshToken 时),并且想要实现一个流程,当服务器注意到它已过期时,令牌会自动刷新.

So we're creating a React-Native app using Apollo and GraphQL. I'm using JWT based authentication(when user logs in both an activeToken and refreshToken is created), and want to implement a flow where the token gets refreshed automatically when the server notices it's been expired.

Apollo-Link-Error 的 Apollo Docs 提供了一个很好的 起点 从 ApolloClient 中捕获错误:

The Apollo Docs for Apollo-Link-Error provides a good starting point to catch the error from the ApolloClient:

onError(({ graphQLErrors, networkError, operation, forward }) => {
  if (graphQLErrors) {
    for (let err of graphQLErrors) {
      switch (err.extensions.code) {
        case 'UNAUTHENTICATED':
          // error code is set to UNAUTHENTICATED
          // when AuthenticationError thrown in resolver

          // modify the operation context with a new token
          const oldHeaders = operation.getContext().headers;
          operation.setContext({
            headers: {
              ...oldHeaders,
              authorization: getNewToken(),
            },
          });
          // retry the request, returning the new observable
          return forward(operation);
      }
    }
  }
})

但是,我真的很难弄清楚如何实现 getNewToken().我的 GraphQL 端点具有创建新令牌的解析器,但我无法从 Apollo-Link-Error 调用它,对吗?

However, I am really struggling to figure out how to implement getNewToken(). My GraphQL endpoint has the resolver to create new tokens, but I can't call it from Apollo-Link-Error right?

如果令牌是在 Apollo 客户端将连接到的 GraphQL 端点中创建的,那么如何刷新令牌?

So how do you refresh the token if the Token is created in the GraphQL endpoint that your Apollo Client will connect to?

推荐答案

示例 是一个很好的起点,但假设 getNewToken() 操作是同步的.

The example given in the the Apollo Error Link documentation is a good starting point but assumes that the getNewToken() operation is synchronous.

在您的情况下,您必须点击 GraphQL 端点以检索新的访问令牌.这是一个异步操作,您必须使用 apollo- 中的 fromPromise 实用程序函数链接 包将您的 Promise 转换为 Observable.

In your case, you have to hit your GraphQL endpoint to retrieve a new access token. This is an asynchronous operation and you have to use the fromPromise utility function from the apollo-link package to transform your Promise to an Observable.

import React from "react";
import { AppRegistry } from 'react-native';

import { onError } from "apollo-link-error";
import { fromPromise, ApolloLink } from "apollo-link";
import { ApolloClient } from "apollo-client";

let apolloClient;

const getNewToken = () => {
  return apolloClient.query({ query: GET_TOKEN_QUERY }).then((response) => {
    // extract your accessToken from your response data and return it
    const { accessToken } = response.data;
    return accessToken;
  });
};

const errorLink = onError(
  ({ graphQLErrors, networkError, operation, forward }) => {
    if (graphQLErrors) {
      for (let err of graphQLErrors) {
        switch (err.extensions.code) {
          case "UNAUTHENTICATED":
            return fromPromise(
              getNewToken().catch((error) => {
                // Handle token refresh errors e.g clear stored tokens, redirect to login
                return;
              })
            )
              .filter((value) => Boolean(value))
              .flatMap((accessToken) => {
                const oldHeaders = operation.getContext().headers;
                // modify the operation context with a new token
                operation.setContext({
                  headers: {
                    ...oldHeaders,
                    authorization: `Bearer ${accessToken}`,
                  },
                });

                // retry the request, returning the new observable
                return forward(operation);
              });
        }
      }
    }
  }
);

apolloClient = new ApolloClient({
  link: ApolloLink.from([errorLink, authLink, httpLink]),
});

const App = () => (
  <ApolloProvider client={apolloClient}>
    <MyRootComponent />
  </ApolloProvider>
);

AppRegistry.registerComponent('MyApplication', () => App);

您可以停留在上述运行正常的实现上,直到两个或多个请求同时失败.因此,要在令牌到期时处理并发请求失败,请查看 这篇文章.

You can stop at the above implementation which worked correctly until two or more requests failed concurrently. So, to handle concurrent requests failure on token expiration, have a look at this post.

这篇关于如何使用 Apollo 和 GraphQL 刷新 JWT 令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆