How to use Redux to refresh JWT token?

后端 未结 3 976
予麋鹿
予麋鹿 2020-12-04 06:17

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

3条回答
  •  日久生厌
    2020-12-04 06:29

    I made a simple wrapper around redux-api-middleware to postpone actions and refresh access token.

    middleware.js

    import { isRSAA, apiMiddleware } from 'redux-api-middleware';
    
    import { TOKEN_RECEIVED, refreshAccessToken } from './actions/auth'
    import { refreshToken, isAccessTokenExpired } from './reducers'
    
    
    export function createApiMiddleware() {
      const postponedRSAAs = []
    
      return ({ dispatch, getState }) => {
        const rsaaMiddleware = apiMiddleware({dispatch, getState})
    
        return (next) => (action) => {
          const nextCheckPostponed = (nextAction) => {
              // Run postponed actions after token refresh
              if (nextAction.type === TOKEN_RECEIVED) {
                next(nextAction);
                postponedRSAAs.forEach((postponed) => {
                  rsaaMiddleware(next)(postponed)
                })
              } else {
                next(nextAction)
              }
          }
    
          if(isRSAA(action)) {
            const state = getState(),
                  token = refreshToken(state)
    
            if(token && isAccessTokenExpired(state)) {
              postponedRSAAs.push(action)
              if(postponedRSAAs.length === 1) {
                return  rsaaMiddleware(nextCheckPostponed)(refreshAccessToken(token))
              } else {
                return
              }
            }
          
            return rsaaMiddleware(next)(action);
          }
          return next(action);
        }
      }
    }
    
    export default createApiMiddleware();
    

    I keep tokens in the state, and use a simple helper to inject Acess token into a request headers

    export function withAuth(headers={}) {
      return (state) => ({
        ...headers,
        'Authorization': `Bearer ${accessToken(state)}`
      })
    }
    

    So redux-api-middleware actions stays almost unchanged

    export const echo = (message) => ({
      [RSAA]: {
          endpoint: '/api/echo/',
          method: 'POST',
          body: JSON.stringify({message: message}),
          headers: withAuth({ 'Content-Type': 'application/json' }),
          types: [
            ECHO_REQUEST, ECHO_SUCCESS, ECHO_FAILURE
          ]
      }
    })
    

    I wrote the article and shared the project example, that shows JWT refresh token workflow in action

提交回复
热议问题