Attach an authorization header for all requests for axioms

I have a reaction / reduction application that retrieves a token from the api server. After user authentication, I would like all axios requests to have this token as an authorization header without having to manually bind it to each request in action. I am new to response / shortening and am not sure about the best approach and cannot find quality hits on Google.

Here is my redux installation:

// actions.js import axios from 'axios'; export function loginUser(props) { const url = `https://api.mydomain.com/login/`; const { email, password } = props; const request = axios.post(url, { email, password }); return { type: LOGIN_USER, payload: request }; } export function fetchPages() { /* here is where I'd like the header to be attached automatically if the user has logged in */ const request = axios.get(PAGES_URL); return { type: FETCH_PAGES, payload: request }; } // reducers.js const initialState = { isAuthenticated: false, token: null }; export default (state = initialState, action) => { switch(action.type) { case LOGIN_USER: // here is where I believe I should be attaching the header to all axios requests. return { token: action.payload.data.key, isAuthenticated: true }; case LOGOUT_USER: // i would remove the header from all axios requests here. return initialState; default: return state; } } 

My token is stored in the redux store under state.session.token .

I lost a little how to continue. I tried to make an axios instance in a file in the root directory and update / import, not from node_modules, but it does not attach the header when the state changes. Any feedback / ideas are greatly appreciated, thanks.

+52
reactjs redux axios
source share
6 answers

There are several ways to achieve this. Here I explained the two most common approaches.

1. You can use axios interceptors to intercept any requests and add authorization headers.

 // Add a request interceptor axios.interceptors.request.use(function (config) { const token = store.getState().session.token; config.headers.Authorization = token; return config; }); 

2. From the axios documentation axios you can see that there is a mechanism that allows you to set a default header that will be sent every time you request it.

 axios.defaults.headers.common['Authorization'] = AUTH_TOKEN; 

So in your case:

 axios.defaults.headers.common['Authorization'] = store.getState().session.token; 

If you want, you can create a self-executing function that itself will set the authorization header when the token is present in the repository.

 (function() { String token = store.getState().session.token; if (token) { axios.defaults.headers.common['Authorization'] = token; } else { axios.defaults.headers.common['Authorization'] = null; /*if setting null does not remove 'Authorization' header then try delete axios.defaults.headers.common['Authorization']; */ } })(); 

Now you no longer need to attach the token manually to each request. You can put the above function in a file that is guaranteed to be executed every time ( for example: A file that contains routes).

Hope it helps :)

+72
source share

The best solution for me is to create a client service that you will create with a token in order to use it to port axios .

 import axios from 'axios'; const client = (token = null) => { const defaultOptions = { headers: { Authorization: token ? `Token ${token}` : '', }, }; return { get: (url, options = {}) => axios.get(url, { ...defaultOptions, ...options }), post: (url, data, options = {}) => axios.post(url, data, { ...defaultOptions, ...options }), put: (url, data, options = {}) => axios.put(url, data, { ...defaultOptions, ...options }), delete: (url, options = {}) => axios.delete(url, { ...defaultOptions, ...options }), }; }; const request = client('MY SECRET TOKEN'); request.get(PAGES_URL); 

In this client, you can also extract the token from localStorage / cookie as you want.

+34
source share

If you use "axios": "^ 0.17.1", you can do like this:

Create an axios instance:

 // Default config options const defaultOptions = { baseURL: <CHANGE-TO-URL>, headers: { 'Content-Type': 'application/json', }, }; // Create instance let instance = axios.create(defaultOptions); // Set the AUTH token for any request instance.interceptors.request.use(function (config) { const token = localStorage.getItem('token'); config.headers.Authorization = token ? `Bearer ${token}` : ''; return config; }); 

Then, for any request, the token will be selected from localStorage and will be added to the request headers.

I use the same instance of the entire application with this code:

 import axios from 'axios'; const fetchClient = () => { const defaultOptions = { baseURL: process.env.REACT_APP_API_PATH, method: 'get', headers: { 'Content-Type': 'application/json', }, }; // Create instance let instance = axios.create(defaultOptions); // Set the AUTH token for any request instance.interceptors.request.use(function (config) { const token = localStorage.getItem('token'); config.headers.Authorization = token ? `Bearer ${token}` : ''; return config; }); return instance; }; export default fetchClient(); 

Good luck.

+31
source share

Similarly, we have a function to set or remove a token from these calls:

 import axios from 'axios'; export default function setAuthToken(token) { axios.defaults.headers.common['Authorization'] = ''; delete axios.defaults.headers.common['Authorization']; if (token) { axios.defaults.headers.common['Authorization'] = `${token}`; } } 

We always clear the existing token during initialization, then install the received one.

+5
source share

If you want to name other api routes in the future and save your token in the store, try using redux middleware .

The middle software can listen to the api action and send api requests through the corresponding axioms respectively.

Here is a very simple example:

actions /api.js

 export const CALL_API = 'CALL_API'; function onSuccess(payload) { return { type: 'SUCCESS', payload }; } function onError(payload) { return { type: 'ERROR', payload, error: true }; } export function apiLogin(credentials) { return { onSuccess, onError, type: CALL_API, params: { ...credentials }, method: 'post', url: 'login' }; } 

middleware /api.js

 import axios from 'axios'; import { CALL_API } from '../actions/api'; export default ({ getState, dispatch }) => next => async action => { // Ignore anything that not calling the api if (action.type !== CALL_API) { return next(action); } // Grab the token from state const { token } = getState().session; // Format the request and attach the token. const { method, onSuccess, onError, params, url } = action; const defaultOptions = { headers: { Authorization: token ? `Token ${token}` : '', } }; const options = { ...defaultOptions, ...params }; try { const response = await axios[method](url, options); dispatch(onSuccess(response.data)); } catch (error) { dispatch(onError(error.data)); } return next(action); }; 
+2
source share

Sometimes there is a case where some requests made with axios point to endpoints that do not accept authorization headers. Thus, an alternative way to set the authorization header only on the allowed domain is the same as in the example below. Place the following function in any file that is executed each time the React application starts, for example, in the routes file.

 export default () => { axios.interceptors.request.use(function (requestConfig) { if (requestConfig.url.indexOf(<ALLOWED_DOMAIN>) > -1) { const token = localStorage.token; requestConfig.headers['Authorization'] = 'Bearer ${token}'; } return requestConfig; }, function (error) { return Promise.reject(error); }); } 
0
source share

All Articles