Reputation: 775
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.
Upvotes: 2
Views: 1131
Reputation: 968
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'
}
})
Upvotes: 2