I am using a JWT Token auth system, and when I login I get the token like this:
axios.post('/login', data)
.then(response => {
localStorage.setItem('token', response.data.token);
});
This works well and the token is saved in localStorage. However, the token is not included in the later requests. The Authorization header is Bearer null
.
This is how I set up my global axios object.
window.axios = axios.create({
baseURL: '/api/',
timeout: 10000,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content,
'Authorization': 'Bearer ' + localStorage.getItem('token')
}
});
If I refresh the site, the token is set, and is used properly.
Edit:
I got it to work by removing the Authorization
header from the create()
method and instead using window.axios.defaults.headers.common['Authorization']
. But now the same problem appears with Laravel Echo. I create the instance like this:
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'xxx',
cluster: 'eu',
encrypted: true,
namespace: 'xxx',
auth: {
headers: {
'Authorization': 'Bearer ' + localStorage.getItem('token')
}
}
});
And I update the header like this:
window.setAuthToken = (token) => {
window.axios.defaults.headers.Authorization = 'Bearer ' + token;
window.Echo.options.auth.headers.Authorization = 'Bearer ' + token;
localStorage.setItem('token', token);
}
The axios header is successfully updated, but not Echo.
However, this option does not allow us to pass in the configs. To correctly set up the headers for each request, we can create an instance of Axios using axios.create and then set a custom configuration on that instance:
You can use axios interceptors for this task. 1-) Inside the successfull login, put the retrieved token to the localStorage. Remove setAuthToken line. .then ( (res) => { setCurrentUser (res.data); localStorage.setItem ("token", res.data.accessToken); setLoading (false); }) 2-) Add this interceptor to your axios instance.
Axios is a flexible and robust solution for making HTTP requests and for intercepting HTTP responses from both Node. js applications and the browser. But, Axios also does much more.
// Get the existing data var existing = localStorage.getItem('myLunch'); // If no existing data, create an array // Otherwise, convert the localStorage string to an array existing = existing ?
Use axios interceptors for this purpose. It will run for every request call.
Better to keep axios methods in a separate file and make call to it than using it directly in all components. This way we can replace axios with another library if we want with minimal effort. Here's what I'm doing in my project.
import axios from "axios";
import AuthService from "./auth";
import config from '../config'
const instance = axios.create({
baseURL: config.apiServer.url,
timeout: config.apiServer.timeout
});
instance.interceptors.request.use(
config => {
const token = AuthService.getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
error => Promise.reject(error)
);
const ApiService = {
get(url) {
return instance.get(url)
.then(res => res)
.catch(reason => Promise.reject(reason));
},
post(url, data) {
return instance.post(url, data)
.then(res => res)
.catch(reason => Promise.reject(reason));
},
awaitAll() {
return axios.all(Array.from(arguments))
.then(axios.spread((...responses) => responses))
.catch(reasons => Promise.reject(reasons));
}
};
export default ApiService;
Now to use it in a component:
ApiService.get(YOUR_GET_URL)
.then(res => {
Console.log(res);
))
.catch(reason => {
console.log(reason);
})
The problem is that your are using localStorage.getItem('token')
at page load. When you are setting it in localStorage
, you have to update it in axios header.
window.axios = axios.create({
baseURL: '/api/',
timeout: 10000,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-TOKEN': document.head.querySelector('meta[name="csrf-token"]').content,
'Authorization': 'Bearer ' + localStorage.getItem('token')
}
});
axios.post('/login', data)
.then(response => {
localStorage.setItem('token', response.data.token);
window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('token');
});
I faced the same problem before and I found out that the file that contains my axios config was being loaded at the time of storing the token, so it was accessing it before it is stored.
The solution is, in axios config:
const axiosInstance = axios.create({
baseURL: `${API_BASE_URL}`,
headers: {
Accepted: 'appication/json',
'Content-Type': 'application/json',
},
});
axiosInstance.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.authorization = token;
}
return config;
},
(error) => Promise.reject(error),
);
export default axiosInstance;
After that, use this instance where you need to make a request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With