When I try to login to my react app it returns as success and saves it in sessionStorage but when I try to access the page which requires Bearer token to fetch data via axios it returns http 401 error.
But when I reload the page, then the result is as required.
import axios from "axios";
let token = JSON.parse(window.sessionStorage.getItem("token"));
let AxiosInstance= axios.create({
baseURL: "https://myurl.com/backend/api/",
timeout: 5000,
headers: { Authorization: "Bearer " + token },
});
export default AxiosInstance;
Your token is being initialized onload so you have to call token in config.headers["Authorization"] on every request through interceptor so you don't need to reload page.
Interceptor:
Axios interceptors are functions that are called before a request is sent and after a response is received
import axios from "axios";
let AxiosInstance = axios.create({
baseURL: "https://myurl.com/backend/api/",
timeout: 5000,
});
AxiosInstance.interceptors.request.use(function (config) {
let token = JSON.parse(window.sessionStorage.getItem("sessionData"));
config.headers["Authorization"] = "Bearer " + token;
return config;
});
export default AxiosInstance;
UPDATE: You can learn more here about Axios interceptors
I'll guess it is because you're creating the axios instance outside any of React's lifecycle
when you run your app and enter your login screen, it makes a Axios instance
import axios from "axios";
let token = JSON.parse(window.sessionStorage.getItem("token"));
let AxiosInstance = axios.create({
baseURL: "https://myurl.com/backend/api/",
timeout: 5000,
headers: { Authorization: "Bearer " + token }, // on the first go token is null
});
export default AxiosInstance;
After you login, your axios instance still has a nulll token, you see, this code is executed once and never more, that's why when you refresh the page, it works, because when this piece of code is executed once again, there's a token in localstorage.
There's a couple things you can do but the easiest i guess it's to use Axios interceptors
AxiosInstace.interceptors.request.use(function (config) {
const token = localStorage.getItem('token');
config.headers.Authorization = token ? `Bearer ${token}` : '';
return config;
});
That way every time you do a request your headers will be updated (not sure if this is the best approach but it works)
Related
I am trying to create and axios instance so that I don't have to write Authorization header on every request. I am storing access token on localStorage.
I tried creating a file axiosInstance.ts
import axios, { AxiosInstance } from "axios"
const service = axios.create({
baseURL: "http://localhost:5000/",
headers: {
Authorization: localStorage && localStorage.getItem("token")
? `Bearer ${localStorage.getItem("token")}`
: "",
},
})
export default service
But it throws localStorage is not defined error.
So I tried to make this a custom hook like this
useAxios.ts
function useAxios() {
const [axiosInstance, setAxiosInstance] = useState<null | AxiosInstance>(null)
useEffect(() => {
const service = axios.create({
baseURL: "http://localhost:5000/",
headers: {
Authorization: localStorage.getItem("token")
? `Bearer ${localStorage.getItem("token")}`
: "",
},
})
setAxiosInstance(service)
}, [])
return axiosInstance
}
export default useAxios
And when i tried to use it like this it threw an error which says service.post is not a function
So when i log the service/axiosInstance it logs a get request promise to baseURL. I am not sure what i am doing wrong.
I send a request to the API for creating an account(I use axios) then API send me a response involve a token. I save this token in local storage.But I don't know how to send it in axios header.
if (this.sendRequest) {
axios.post(url, data)
.then((res) => {
if (res.data.type === "success") {
localStorage.setItem("token",res.data.data);
}
})
.catch((err) => this.msg.push("error" + err.response.status));
}
To do this, follow the steps below:
1- create a folder in your project called Services. Then create another directory in that folder called Config. Inside that folder create a .js file called auth-axios.js as follows:
In this file, you use the following code. By doing this, you inform the application that every time you want to call the API, you must go through this port and you must set the base URL and header in the API automatically:
import axios from "axios";
import authService from "../modules/authService";
import Vue from "vue";
const headers = {
"content-type": "application/json",
Accept: "application/json",
"Accept-Language": "fa",
version: "1000"
};
const API_V1 = axios.create({
baseURL: process.env.VUE_APP_BASE_URL_V1,
headers: headers
});
const API_DEV = axios.create({
baseURL: process.env.VUE_APP_BASE_URL_DEV,
headers: headers
});
API_DEV.interceptors.request.use(
config => {
const token = authService.getAccessToken();
if (token) {
config.headers["Authorization"] = "Bearer " + token;
}
return config;
},
error => {
Promise.reject(error);
}
);
export { API_V1, API_V4, API_DEV };
Now for the services that you have in the application, you have to create a separate file in the same services directory and use the API_1 variable in that file.
for example, create accountServices.js and on this file call API by this way:
import { API_V1 } from "../config/auth-axios";
class employerServices {
createAccount(body) {
return API_V1.post("test-API-URL", body);
}
}
export default new employerServices();
I am trying to call an API to get current user details and need to attach token with the Authorization header. However it is failing to call API with 500 error response.
It is working absolutely fine from Postman and curl command and I am getting user details.
Code for it as below:
httpHeaders = new HttpHeaders ({
'Content-Type': 'application/json'
});
getCurrentUser(url){
var token = localStorage.getItem('token');
this.httpHeaders = this.httpHeaders.set('Authorization', `Bearer ${localStorage.getItem('token')}`);
return this.http.get<any>(url, { headers: this.httpHeaders });
}
I tried different ways to concatenate token with Bearer prefix however getting Authorization in console as Bearer "token-string" (not sure if this is the reason my API is failing).
public getCurrentUser(url: string): Observable<unknown> {
const token = localStorage.getItem('token');
// Launch DevTools to step through the code in the debugger;
debugger;
// check if token is valid string as well
if (token == null) {
throw new Error('Authorization token not found');
}
// Use local object
const httpHeaders = new HttpHeaders({
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
});
return this.http.get<unknown>(url, { headers: httpHeaders });
}
If you still receive HTTP 500 internal server error from server:
Open DevTools and review the error messages in Console or Network tab if any.
Review the server logs if you have access to them.
I am building an Vue.js app that relies heavily on api calls. I am using axios to make call.
I am using a pattern similar this. Basically I have created a service that will be shared by all the components.
Following is the service:
//api-client.js
import axios from 'axios'
import store from '../src/store'
let authKey = store.getters.getAuthKey
export default axios.create({
withCredentials: false, // This is the default
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: "Basic "+authKey
}
})
Now notice I am using a getter to get auth token for the vuex store and seting it in the service.
I will use this service like:
//App.vue
<template>
<div>
<!-- some code -->
</div>
</template>
<script>
import apiClient from "../api-client.js"
export default {
mounted(){
apiClient.get("#url").then(()={
// Do Something
})
}
}
</script>
<style lang="scss">
</style>
The situation is, auth key changes every now and then, so I have a setting that will update the auth key in the store.
The setting updates the auth key in store successfully, but the key in api-client.js is not updated. It is loaded only once and the update in the store is not cascaded to this api-client.js.
Is there any pattern to solve this? Please suggest.
Since your token is dynamic, you can't define it in your axios instance factory headers setup. Best way to handle this globally is to use request interceptors
//api-client.js
import axios from 'axios'
import store from '../src/store'
const apiClient = axios.create({
withCredentials: false, // This is the default
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});
apiClient.interceptors.request.use(function (config) {
// Do something before request is sent
let authKey = store.getters.getAuthKey
config.headers["Authorization"] = "Basic " + authKey;
return config;
});
export default apiClient;
This way interceptor function would occur on each request and would pickup latest version of your authKey;
node
const LocalStorage = require ('node-localstorage').LocalStorage;
localStorage = new LocalStorage('./localStorage');
localStorage.setItem('username', user.name);
localStorage.setItem('token', user.token)
react
const author = localStorage.getItem('username')
const token = localStorage.getItem('token')
In react console.log(localStorage) // {}
P.S: maybe need send from react to node GET request?
fetch('/api', {
method: 'GET'
I Assume that you are trying to make request along with the token that you have saved in locastorage. for that you have to add Authorization headers. like
const token = localStorage.getItem('token')
fetch('https://example.com/endpoint', {
method: 'GET',
headers: {
'Authorization': token
}
})
to get the token create a specific route like
first you need to import
import jwt from 'jwt-simple';
Then
app.post('/login',function(req,res,next){
res.send({token:jwt.encode({sub:user.id,iat:timpestamp},SecretKey)});
});
where SecretKey is the key defined to encryption and here the userId with time is taken to generate the token