Skip to content

Middleware to help with header management when using Redux, Devise Token Auth, and Axios

Notifications You must be signed in to change notification settings

wdjungst/redux-devise-axios

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

About

This package fits a very specific use case. It's purpose is to keep help keep track of new tokens everytime a request is made. It works by capturing the dispatch and updating the axios config with the new headers recieved from devise. There is also a validate token option as well as a logout option.

  • You are using devise token authentiation
  • You are using axios
  • You are using redux

Installation

npm install redux-devise-axios

store.js

import { createStore, compose, applyMiddleware } from 'redux';

//This could be saga or promise or any other async middleware
import thunk from 'redux-thunk';

import apiMiddleware from 'redux-devise-axios';

import rootReducer from './reducers/index';
import axios from 'axios';


/* OPTIONS
  axios: Your axios instance *required
  customHeaders: An array of headers you want to add.  Defaults: ['access-token', 'token-type', 'client', 'expiry', 'uid']
  validateAction: default 'VALIDATE_TOKEN'
  logoutAction: default 'LOGOUT'
*/
const options = { axios }


//redux-devise-axios middleware must come after your async middleware
const enhancers = compose(
  applyMiddleware(thunk, apiMiddleware(options)),
  window.devToolsExtension ? window.devToolsExtension() : f => f
);

const store = createStore(rootReducer, {}, enhancers);

Options

  • axios: This is your instance of axios and is required
  • customHeaders: Array of additional Headers you want to use
    • default: ['access-token', 'token-type', 'client', 'expiry', 'uid'] This is what devise sends by default
  • validateAction: This is the action you dispatch in an HOC (Usually because the user refreshed the browser)
    • default: 'VALIDATE_TOKEN'
  • logoutAction: This is the action you dispatch to logout your user.
    • default: 'LOGOUT'

NOTE: You are resposible for the implementation of LOGOUT and VALIDATE token. These actions simply add to and clear localStorage.

Example Usage

actions/auth.js

import axios from 'axios';
import { setFlash } from '../actions/flash';

export const registerUser = (email, password, passwordConfirmation, history) => {
  return(dispatch) => {
    axios.post('/api/auth', { email, password, password_confirmation: passwordConfirmation })
      .then( res => {
        let { data: { data: user }, headers } = res;
        dispatch({ type: 'LOGIN', user, headers });
        history.push('/');
      })
      .catch( res => {
        const message = res.response.data.errors.full_messages.join(',');
        dispatch(setFlash(message, 'error'));
    });
  }
}

export const handleLogout = (history) => {
  return(dispatch) => {
    axios.delete('/api/auth/sign_out')
      .then( res => {
        dispatch({ type: 'LOGOUT' });
        dispatch(setFlash('Logged out successfully!', 'success'));
        history.push('/login');
      })
      .catch( res => {
        // TODO: handle errors for the client
        console.log(res);
      });
    }
}

export const handleLogin = (email, password, history) => {
  return(dispatch) => {
    axios.post('/api/auth/sign_in', { email, password })
      .then( res => {
        let { data: { data: user }, headers } = res
        dispatch({ type: 'LOGIN', user, headers });
        history.push('/');
      })
      .catch( res => {
        // TODO: handle errors for the client
        console.log(res);
      })
  }
}

export const validateToken = (cb = f => f) => {
  return (dispatch) => {
    dispatch({ type: 'VALIDATE_TOKEN' })
    let headers = axios.defaults.headers.common
    axios.get('/api/auth/validate_token', headers)
      .then( res => dispatch({ type: 'LOGIN', user: res.data.data }) )
      .catch(() => cb())
  }
}

Notice that we are sending the headers when we dispatch. This is key to how this package works. Anytime any action is dispatched with a key of headers axios headers will be updated.

This will work for React State as well as long as you dispatch some action with the res.headers from axios.

  componentDidMount() {
    axios.get('/api/bio')
      .then( res => {
        this.setState({ bio: res.data.body });
        this.props.dispatch(setHeaders(res.headers))
      })
      .catch( res => {
        console.log(`Bio GET Fail: ${res}`);
      });
  }

Demo

  $ clone project
  $ cd demo
  $ bundle
  $ bundle exec rake db:create db:migrate
  $ rails s -p 3001
  $ cd client (new tab / pane)
  $ yarn or npm install
  $ yarn start or npm start

About

Middleware to help with header management when using Redux, Devise Token Auth, and Axios

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published