小编典典

如何使用Redux刷新JWT令牌?

reactjs

我们的React Native Redux应用程序使用JWT令牌进行身份验证。有许多操作需要此类令牌,​​并且例如在应用加载时会同时分派许多令牌。

例如

componentDidMount() {
    dispath(loadProfile());
    dispatch(loadAssets());
    ...
}

双方loadProfileloadAssets要求JWT。我们将令牌保存在和中AsyncStorage。我的问题是如何处理令牌到期。

最初,我将使用中间件来处理令牌到期

// jwt-middleware.js

export function refreshJWTToken({ dispatch, getState }) {

  return (next) => (action) => {
    if (isExpired(getState().auth.token)) {
      return dispatch(refreshToken())
          .then(() => next(action))
          .catch(e => console.log('error refreshing token', e));
    }
    return next(action);
};

}

我遇到的问题是,对于令牌loadProfileloadAssets操作,都会刷新令牌,因为在分发令牌和令牌时,令牌将过期。理想情况下,我想“暂停”需要身份验证的操作,直到刷新令牌为止。有没有办法用中间件做到这一点?


阅读 251

收藏
2020-07-22

共1个答案

小编典典

我找到了解决此问题的方法。我不确定这是否是最佳做法,并且可能会有一些改进。

我最初的想法仍然存在:JWT刷新位于中间件中。thunk如果thunk使用中间件,则必须先使用它。

...
const createStoreWithMiddleware = applyMiddleware(jwt, thunk)(createStore);

然后,在中间件代码中,我们检查令牌是否在任何异步操作之前到期。如果过期,我们还将检查是否已经在刷新令牌-
为了能够进行此类检查,我们向该州添加了对新令牌的承诺。

import { refreshToken } from '../actions/auth';

export function jwt({ dispatch, getState }) {

    return (next) => (action) => {

        // only worry about expiring token for async actions
        if (typeof action === 'function') {

            if (getState().auth && getState().auth.token) {

                // decode jwt so that we know if and when it expires
                var tokenExpiration = jwtDecode(getState().auth.token).<your field for expiration>;

                if (tokenExpiration && (moment(tokenExpiration) - moment(Date.now()) < 5000)) {

                    // make sure we are not already refreshing the token
                    if (!getState().auth.freshTokenPromise) {
                        return refreshToken(dispatch).then(() => next(action));
                    } else {
                        return getState().auth.freshTokenPromise.then(() => next(action));
                    }
                }
            }
        }
        return next(action);
    };
}

最重要的部分是refreshToken功能。该功能需要在刷新令牌时分派操作,以便状态将包含对新令牌的承诺。这样,如果我们调度同时使用令牌认证的多个异步操作,则令牌仅刷新一次。

export function refreshToken(dispatch) {

    var freshTokenPromise = fetchJWTToken()
        .then(t => {
            dispatch({
                type: DONE_REFRESHING_TOKEN
            });

            dispatch(saveAppToken(t.token));

            return t.token ? Promise.resolve(t.token) : Promise.reject({
                message: 'could not refresh token'
            });
        })
        .catch(e => {

            console.log('error refreshing token', e);

            dispatch({
                type: DONE_REFRESHING_TOKEN
            });
            return Promise.reject(e);
        });



    dispatch({
        type: REFRESHING_TOKEN,

        // we want to keep track of token promise in the state so that we don't try to refresh
        // the token again while refreshing is in process
        freshTokenPromise
    });

    return freshTokenPromise;
}

我意识到这很复杂。我也担心调度refreshToken动作本身不是动作。请让我知道您知道的其他使用Redux处理过期JWT令牌的方法。

2020-07-22