Attach Authorization header for all axios requests

前端 未结 9 1957
灰色年华
灰色年华 2020-12-04 05:17

I have a react/redux application that fetches a token from an api server. After the user authenticates I\'d like to make all axios requests have that token as an Authorizati

相关标签:
9条回答
  • 2020-12-04 05:20

    If you want to call other api routes in the future and keep your token in the store then try using redux middleware.

    The middleware could listen for the an api action and dispatch api requests through axios accordingly.

    Here is a very basic 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's 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);
    };
    
    0 讨论(0)
  • 2020-12-04 05:24

    There are multiple ways to achieve this. Here, I have 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 documentation of axios you can see there is a mechanism available which allows you to set default header which will be sent with every request you make.

    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-executable function which will set authorization header itself when the token is present in the store.

    (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 token manually to every request. You can place the above function in the file which is guaranteed to be executed every time (e.g: File which contains the routes).

    Hope it helps :)

    0 讨论(0)
  • 2020-12-04 05:24
    export const authHandler = (config) => {
      const authRegex = /^\/apiregex/;
    
      if (!authRegex.test(config.url)) {
        return store.fetchToken().then((token) => {
          Object.assign(config.headers.common, { Authorization: `Bearer ${token}` });
          return Promise.resolve(config);
        });
      }
      return Promise.resolve(config);
    };
    
    axios.interceptors.request.use(authHandler);
    

    Ran into some gotchas when trying to implement something similar and based on these answers this is what I came up with. The problems I was experiencing were:

    1. If using axios for the request to get a token in your store, you need to detect the path before adding the header. If you don't, it will try to add the header to that call as well and get into a circular path issue. The inverse of adding regex to detect the other calls would also work
    2. If the store is returning a promise, you need to return the call to the store to resolve the promise in the authHandler function. Async/Await functionality would make this easier/more obvious
    3. If the call for the auth token fails or is the call to get the token, you still want to resolve a promise with the config
    0 讨论(0)
  • 2020-12-04 05:29

    Similarly, we have a function to set or delete the token from calls like this:

    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 clean the existing token at initialization, then establish the received one.

    0 讨论(0)
  • 2020-12-04 05:30

    Try to make new instance like i did below

    var common_axios = axios.create({
        baseURL: 'https://sample.com'
    });
    
    // Set default headers to common_axios ( as Instance )
    common_axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
    // Check your Header
    console.log(common_axios.defaults.headers);
    

    How to Use it

    common_axios.get(url).......
    common_axios.post(url).......
    
    0 讨论(0)
  • 2020-12-04 05:30

    The point is to set the token on the interceptors for each request

    import axios from "axios";
        
    const httpClient = axios.create({
        baseURL: "http://youradress",
        // baseURL: process.env.APP_API_BASE_URL,
    });
    
    httpClient.interceptors.request.use(function (config) {
        const token = localStorage.getItem('token');
        config.headers.Authorization =  token ? `Bearer ${token}` : '';
        return config;
    });
    
    0 讨论(0)
提交回复
热议问题