如何使用Redux刷新JWT令牌? [英] How to use Redux to refresh JWT token?

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

问题描述

我们的React Native Redux应用程序使用JWT令牌进行身份验证.有许多动作需要这样的令牌,并且许多令牌是同时分发的,例如应用加载时.

Our React Native Redux app uses JWT tokens for authentication. There are many actions that require such tokens and a lot of them are dispatched simultaneously e.g. when app loads.

例如

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

loadProfileloadAssets都需要JWT.我们将令牌保存在状态和AsyncStorage中.我的问题是如何处理令牌到期.

Both loadProfile and loadAssets require JWT. We save the token in the state and AsyncStorage. My question is how to handle token expiration.

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

Originally I was going to use middleware for handling token expiration

// 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动作都将刷新令牌,因为在分发它们时,令牌将过期.理想情况下,我想暂停"需要身份验证的操作,直到刷新令牌为止.有没有办法用中间件来做到这一点?

The problem that I ran into was that refreshing of the token will happen for both loadProfile and loadAssets actions because at the time when they are dispatch the token will be expired. Ideally I would like to "pause" actions that require authentication until the token is refreshed. Is there a way to do that with middleware?

推荐答案

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

I found a way to solve this. I am not sure if this is best practice approach and there are probably some improvements that could be made to it.

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

My original idea stays: JWT refresh is in the middleware. That middleware has to come before thunk if thunk is used.

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

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

Then in the middleware code we check to see if token is expired before any async action. If it is expired we also check if we are already are refreshing the token -- to be able to have such check we add promise for fresh token to the state.

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功能.该功能需要在刷新令牌时分派操作,以便状态将包含对新令牌的承诺.这样,如果我们调度同时使用令牌认证的多个异步操作,令牌将仅刷新一次.

The most important part is refreshToken function. That function needs to dispatch action when token is being refreshed so that the state will contain the promise for the fresh token. That way if we dispatch multiple async actions that use token auth simultaneously the token gets refreshed only once.

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令牌的方法.

I realize that this is pretty complicated. I am also a bit worried about dispatching actions in refreshToken which is not an action itself. Please let me know of any other approach you know that handles expiring JWT token with redux.

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

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