Home > database >  What is the correct way to pass a token to axios from React?
What is the correct way to pass a token to axios from React?

Time:10-01

The question sounds vague so allow me to explain. I am wondering, what is the correct/best way to pass get a token from local storage and pass it into my axios request.

This is what I am doing now, and I am sure this is not correct so I want to fix it but am unsure how.

I have a component called TicketsComponent that requires authorization. Therefore, in componentDidMount(), I validate the token, and if its invalid then send the user back to login, otherwise, load the tickets. It looks like this:

  componentDidMount() {
    this._isMounted = true;

    // validate token
    const token = localStorage.getItem("token");
    AuthService.validateToken()
      .then((res) => {
        if (res == undefined || res == null || !token) {
          this.props.history.push("/login");
        }
      })
      .then(() => {
        TicketService.getTickets().then((res) => {
          if (this._isMounted) {
            this.setState({ tickets: res.data });
          }
        });
      });
  }

Both AuthService.validateToken() and TicketService.getTickets() require the JWT in the header. Here are those two functions:

  validateToken() {
    return axios
      .get(API_BASE_URL   "authenticate", {
        headers: {
          token: this.getTokenFromLocalStorage(),
        },
      })
      .then("did it")
      .catch((error) => {
        console.log("failed to validate token"   error);
        return null;
      });
  }
  getTickets() {
    console.log("getting tickets!");
    console.log("Environment variable: "   process.env.NODE_ENV);
    return axios
      .get(API_BASE_URL   "tickets", {
        headers: { Authorization: `Bearer ${this.getTokenFromLocalStorage()}` },
      })
      .then("yessssss")
      .catch((error) => {
        console.log("failed to get tickets"   error);
      });
  }

The problem is that both AuthService and TicketService share the same function called getTokenFromLocalStorage(). That looks like this:

  getTokenFromLocalStorage() {
    const token = localStorage.getItem("token");
    console.log("the token is -> "   token);
    if (token === null) {
      return undefined;
    }
    return token;
  }
  catch(err) {
    return undefined;
  }

So obviously this is not ideal. I have the same function in two services just to get the token from the header. What is the recommended way of doing this?

EDIT: I hope this kind of question is allowed. Even though the code is not actually broken per se, I still think this is useful to beginners like me to implement best practice.

CodePudding user response:

You can create a shared axios instance like so:

const API_BASE_URL = 'https://example.com/api/'

const instance = axios.create({
  baseURL: API_BASE_URL,
  headers: { Authorization: `Bearer ${this.getTokenFromLocalStorage()}` },
});

Then you'd just import "instance" into the components and call:

import {instance} from '../wherever' // decide if you want to import default or not 

// make sure to either include or exclude the / in the first parameter passed into the request method (e.g. '/authenticate' or 'authenticate') below based on whether you provided a / in the API_BASE_URL

instance.post('authenticate', {
  // any additional config relevant to the request, e.g:
  data: {
    username: 'my user!',
    password: 'super_secret_password'
  }
})
  • Related