- Published on
How to handle Authentication in React
- Authors
- Name
- Ashik Nesin
- @AshikNesin
Here's a little snippet on how to do it.
// auth.js
import { API_ROOT } from 'constants';
import axios, { get, post } from 'axios';
import { push } from 'react-router-redux';
import jwtDecode from 'jwt-decode';
import { isJWT } from 'utils/common';
// ------------------------------------
// Constants
// ------------------------------------
export const SIGIN_REQUEST = 'SIGIN_REQUEST';
export const SIGIN_SUCCESS = 'SIGIN_SUCCESS';
export const SIGIN_FAILURE = 'SIGIN_FAILURE';
export const AUTH_USER = 'AUTH_USER';
export const UNAUTH_USER = 'UNAUTH_USER';
// ------------------------------------
// Actions
// ------------------------------------
export const initAuthState = () => {
const token = localStorage.getItem('token');
return (dispatch, getState) => {
dispatch(authUser(token));
};
};
export const authUser = token => {
// Lets intercept all ajax calls and include token in it.
axios.defaults.headers.token = token;
// Store in the localStorage
localStorage.setItem('token', token);
return (dispatch, getState) => {
dispatch({
type: AUTH_USER,
payload: {
token,
},
});
dispatch({ type: SIGIN_REQUEST });
};
};
export const signoutUser = () => {
localStorage.removeItem('token');
axios.defaults.headers.token = null;
return (dispatch, getState) => {
dispatch(push('/login'));
dispatch({ type: UNAUTH_USER });
};
};
export const signinUser = data => {
return (dispatch, getState) => {
const url = `${API_ROOT}/login`;
dispatch({ type: SIGIN_REQUEST });
const request = post(url, data)
.then(response => {
dispatch({
type: SIGIN_SUCCESS,
payload: response.data,
});
dispatch(authUser(response.data.token));
})
.catch(err => {
dispatch({
type: SIGIN_FAILURE,
payload: err.response.data,
});
});
};
};
export const actions = {
authUser,
signinUser,
signoutUser,
};
// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
[SIGIN_REQUEST]: (state, action) => {
return { ...state, loading: true, errorMsg: '' };
},
[SIGIN_SUCCESS]: (state, action) => {
return { ...state, loading: false, errorMsg: '' };
},
[SIGIN_FAILURE]: (state, action) => {
const errorMsg = action.payload.message || 'Invalid Credentials';
return { ...state, loading: false, errorMsg };
},
[AUTH_USER]: (state, action) => {
const { token } = action.payload;
return { ...state, token, role, id, authenticated: true, loading: false };
},
[UNAUTH_USER]: (state, action) => {
return {
...state,
token: null,
role: null,
authenticated: false,
loading: false,
};
},
};
// ------------------------------------
// Reducer
// ------------------------------------
const initialState = {
loading: false,
errorMsg: '',
role: '',
token: '',
authenticated: false,
};
export default function authReducer(state = initialState, action) {
const handler = ACTION_HANDLERS[action.type];
return handler ? handler(state, action) : state;
}
// reducer.js
export const makeRootReducer = asyncReducers => {
return combineReducers({
auth: authReducer,
...asyncReducers,
});
};