使用 apollo-client + firebase auth 刷新令牌

问题描述 投票:0回答:2

在使用 apollo-client 和 firebase 的 auth 服务时,我在确定令牌刷新时遇到了一些麻烦。

我之前已经使用apollo客户端设置了令牌刷新。通常我使用 apollo-link-error 包(apollo-link-error 文档)。

我的理解是你从 firebase auth 获得最新的令牌,并承诺如下:

firebase.auth().currentUser.getIdToken

如何使用Firebase的refreshToken重新进行身份验证?

阅读这篇文章的答案

当您从浏览器拨打电话时 .getIdToken(true) 将自动 刷新您的令牌。

根据我上面的阅读,我想出了下面的片段

import { onError } from 'apollo-link-error';
import { Observable } from 'apollo-link'; // <-- Add Observable
import firebase from 'lib/firebase';

const errorLink = onError(
  ({ graphQLErrors, networkError, operation, forward }) => {

    let accessToken = window.localStorage.getItem('access_token');

    if (graphQLErrors) {
      // User access token has expired
      if (graphQLErrors[0].message.includes('Signature has expired')) {

        if (accessToken && accessToken !== 'undefined') {

          // Let's refresh token through async request
          return new Observable(observer => {
            firebase
              .auth()
              .currentUser.getIdToken(true)
              .then(function(idToken) {
                if (!idToken) {
                  window.localStorage.removeItem('access_token');
                  return console.log('Refresh token has expired');
                }

                window.localStorage.setItem('access_token', idToken);

                // reset the headers
                operation.setContext(({ headers = {} }) => ({
                  headers: {
                    // Re-add old headers
                    ...headers,
                    // Switch out old access token for new one
                    'login-token': idToken || null
                  }
                }));
                const subscriber = {
                  next: observer.next.bind(observer),
                  error: observer.error.bind(observer),
                  complete: observer.complete.bind(observer)
                };

                // Retry last failed request
                forward(operation).subscribe(subscriber);
              })
              .catch(error => {
                // No refresh or client token available, we force user to login
                observer.error(error);
              });
          });
        }
      }
    }
  }
);

export default errorLink;

javascript firebase firebase-authentication react-apollo apollo-client
2个回答
2
投票

上面的代码确实有效!

我的问题在这里:

if (graphQLErrors[0].message.includes('Signature has expired')) {

我的服务器的错误消息实际上是“令牌已过期”。我改变了上面的 if 语句,一切都很好!

我在网上没有找到很多 apollo-client + firebase-auth 的示例,所以希望这个面包屑可以在使用 apollo-client 和 firebase auth 时帮助其他人。


0
投票

我认为有一种更简洁的方法可以通过添加一个监听器来进行身份验证更改。

import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import { getAuth, onAuthStateChanged } from "firebase/auth";

const httpLink = new HttpLink({ uri: 'https://your-api/graphql' });

const authLink = setContext(async (_, { headers }) => {
  const auth = getAuth();
  const token = await new Promise((resolve, reject) => {
    onAuthStateChanged(auth, user => {
      if (user) {
        user.getIdToken().then(resolve, reject);
      } else {
        resolve('');
      }
    });
  });

  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : "",
    }
  };
});

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
});
© www.soinside.com 2019 - 2024. All rights reserved.