import { REHYDRATE } from 'redux-persist/constants'
import {
  refreshAuthenticationToken,
  scheduleAuthRefresh,
} from '../actions/authentication'
import { AUTHENTICATION } from '../constants/action_types'

const toMilliseconds = seconds => seconds * 1000

// Get a timeout value about 100ms before a given date,
// or at least not in the past
const futureTimeout = time => {
  let msFromNow = time - new Date()

  // Establish a lead time of 100ms before expiration date
  msFromNow = msFromNow - 100

  // Let's not set a timeout for in the past
  return Math.max(msFromNow, 0)
}

export const authentication = store => next => action => {
  const { payload, type } = action

  switch (type) {
    case REHYDRATE:
      if (action.key === 'authentication') {
        const { createdAt, expiresIn, refreshToken } = payload

        if (!refreshToken) break

        const now = new Date()
        const expirationDate = new Date(toMilliseconds(createdAt + expiresIn))

        if (expirationDate < now) {
          store.dispatch(refreshAuthenticationToken(refreshToken))
        } else {
          const newTimeout = futureTimeout(expirationDate)

          store.dispatch(scheduleAuthRefresh(refreshToken, newTimeout))
        }
      }

      break
    case AUTHENTICATION.REFRESH_SUCCESS:
    case AUTHENTICATION.USER_SUCCESS:
      store.dispatch(scheduleAuthRefresh(
        payload.response.refreshToken,
        toMilliseconds(7100)
      ))
      break
    default:
      break
  }

  next(action)
}

import { REHYDRATE } from 'redux-persist/constants'
import {
  refreshAuthenticationToken,
  scheduleAuthRefresh,
} from '../actions/authentication'
import { AUTHENTICATION } from '../constants/action_types'

const toMilliseconds = seconds => seconds * 1000

// Get a timeout value about 100ms before a given date,
// or at least not in the past
const futureTimeout = time => {
  let msFromNow = time - new Date()

  // Establish a lead time of 100ms before expiration date
  msFromNow = msFromNow - 100

  // Let's not set a timeout for in the past
  return Math.max(msFromNow, 0)
}

export const authentication = store => next => action => {
  const { payload, type } = action

  switch (type) {
    case REHYDRATE:
      if (action.key === 'authentication') {
        const { createdAt, expiresIn, refreshToken } = payload

        if (!refreshToken) break

        const now = new Date()
        const expirationDate = new Date(toMilliseconds(createdAt + expiresIn))

        if (expirationDate < now) {
          store.dispatch(refreshAuthenticationToken(refreshToken))
        } else {
          const newTimeout = futureTimeout(expirationDate)

          store.dispatch(scheduleAuthRefresh(refreshToken, newTimeout))
        }
      }

      break
    case AUTHENTICATION.REFRESH_SUCCESS:
    case AUTHENTICATION.USER_SUCCESS:
      store.dispatch(scheduleAuthRefresh(
        payload.response.refreshToken,
        toMilliseconds(7100)
      ))
      break
    default:
      break
  }

  return next(action)
}

Make sure the auth middleware returns
Make sure the auth middleware returns

Thus not breaking the chain of middleware return values
