I'm using axios to send a post request, here's my code:
const getHeaders = (token) => {
const headers = {
"content-type": "application/json",
}
if (token !== undefined) headers.Authorization = `Bearer ${token}`;
return headers;
}
const post = async ({ url, body = {}, token }) => {
const requestObject = {
headers: getHeaders(token),
...body
}
console.log(requestObject);
return await axios.post(url, requestObject);
}
This works when there's no token (for example, the login request), it sends it alright. However, for the next request, I pass a token to request the user details (for example), but when I look at the Chrome network tab, I see this:
So, the headers are being sent as the payload, but then, in the request headers, the "Authorization: Bearer ..." is not there. What am I doing wrong?
If you want to send options you need a third argument....
const post = ({ url, body = {}, token }) => {
const options = {
headers: getHeaders(token)
}
return axios.post(url,body, options);
}
Also async/ await makes no sense here
Related
I am new to using Axios configuration. **So I am wondering if it is possible to set axios header dynamically?**
Because the end points I am calling right now need a Authentication and different authentication for different api, so I want make a change to the created axios instance’s header when token is expired and with different URL.
Here is my current code:
in config.js
import axios from 'axios'
// to get Authorization for api_1
const {access_token_1} = axios.get('url/access_token_1')
// to get Authorization for api_2
const {access_token_2} = axios.get('url/access_token_2')
export const instance = axios.create({
headers: { Authorization: `Bearer ${access_token_1}` },
})
My Api_1 and 2 call
//Api_1
export const getCountry = async (country: string) => {
const response = await instance.get(
`/sas/${country}`
)
return response.data
}
//Api_2
export const getCity = async (city: string) => {
const response = await instance.get(
`/sps/${city}`
)
return response.data
}
I know header can be set again by certain method, but how could I set it again only when it’s expired and set the instance with right authentication for certain Api
Have a look at this documentation, you can create/update headers and pass them to your axios instance. I think this examples might help a little
axios.defaults.baseURL = 'https://api.example.com';
// Important: If axios is used with multiple domains, the AUTH_TOKEN will be sent to all of them.
// See below for an example using Custom instance defaults instead.
axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url,
};
axios(options);
axios.get('https://example.com/getSomething', {
headers: {
Authorization: 'Bearer ' + token //the token is a variable which holds the token
}
})
I'm working with security and have a task which is bind to jwt. When i received jwt and have already saved it in LocalStorage, i was trying to send requests to the server and put this jwt in headers: Authorization: "bearer " + jwt, but server only returned status 403 forbidden. I thought, that the reason is in requests that sending earlier then token was put in header, but i've tried to put this token artificially and server also returned 403, in postman everything works well
this is my axios instance
const TOKEN_STRING = localStorage.getItem("jwt") || ""
export const axiosInstance = axios.create({
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + TOKEN_STRING,
},
})
thats how i save token in the login page
const submit = async () => {
try {
await axios
.post(baseUrl + "/api/login", loginData)
.then((res) => localStorage.setItem("jwt", res.data.jwt))
} catch (e) {
setError(e.message)
}
}
and this how i send request, which is after login page so as i think should be after localStorage receives token
const fetchData = async () => {
try {
await axiosInstance
.get(process.env.REACT_APP_BASE_BACKEND_URL + "/api/discounts")
.then((response) =>
setDiscounts(() =>
response.data.map((el, index) => ({
...el,
img: cardImages[index],
}))
)
)
} catch (e) {
setDiscountsFetchError(e.message)
}
}
useEffect(() => {
fetchData()
}, [])
i think it's enough for example but if smbd needs more info i'll give
I think you creating the axios instance way before your login call so the jwt is empty at that time.
Try the following in your fetch data request after login call, when jwt is present in local storage.
axiosInstance
.get(
process.env.REACT_APP_BASE_BACKEND_URL + "/api/discounts",
{
headers: {
Accept: "application/json",
"Content-Type": "application/json"
Authorization: 'Bearer ' + localStorage.getItem("jwt")
}
})
I have an axios apiClient and I'm trying to get the email stored in localStorage into the header. In my component I tried using
response.headers['email']
and assigning it to an email variable but I'm getting undefined. I'm getting the email in localStorage but not able to get it in the component. Any help will be greatly appreciated.
Axios
const apiClient = axios.create({
baseURL: `${API}`,
withCredentials: false,
headers: {
Accept: "application/json",
"Content-Type": "application/json"
}
});
apiClient.interceptors.request.use(function (config) {
let token = JSON.parse(localStorage.getItem('token'));
let email = JSON.parse(localStorage.getItem('email'));
if (token) {
config.headers.Authorization = `Bearer ${token}`;
config.headers.email = `${email}`;
}
return config;
}, function (err) {
return Promise.reject(err);
});
Here is the method in my component where I need the email data
methods: {
getOrders(){
service.getAllOrders()
.then(response => {
this.email = response.headers['email'];
console.log("email:", this.email)
})
}
}
getAllOrders() does an axios get.
You set the request interceptor but you're checking the response header, and those are two different objects. The response is from the server and won't be affected by a request interceptor.
You can create a different interceptor for the response:
apiClient.interceptors.response.use((response) => {
response.headers.email = JSON.parse(localStorage.getItem('email'));
return response;
});
I'm building a NextJS app, and I'm trying the access a cookie so I can use it to set a Http Header for GraphQL Request, I am using apollo-link-context. This is the code to create the ApolloClient
function createApolloClient(initialState = {}) {
const httpLink = new HttpLink({ uri: `${baseUrl}/graphql`, credentials: 'same-origin', fetch })
const authLink = setContext((_, prevCtx) => {
let token = ''
if (typeof window === 'undefined') token = getCookieFromServer(authCookieName, REQ)
else token = getCookieFromBrowser(authCookieName)
return ({ headers: { 'Auth-Token': token } })
})
const client = new ApolloClient({
ssrMode: typeof window === 'undefined',
cache: new InMemoryCache().restore(initialState),
link: authLink.concat(httpLink)
})
return client
}
The issue here is that the getCookieFromServer function expects an Express Request as the second argument, so it can extract the cookie from req.headers.cookie, and I have no idea where I can get it from there.
I finally found a way. Whenever I send a request from the server (in PageComponent.getInitialProps), I set the header in the context, then I can access it from setContext:
PageComponent.getInitialProps = async (ctx) => {
...
const token = getCookieFromServer(authCookieName, ctx.req)
const { data } = await client.query({
query,
context: { headers: { 'Auth-Token': token } }
})
...
}
Then in setContext:
const authLink = setContext((_, prevCtx) => {
let headers = prevCtx.headers || {}
if (!headers['Auth-Token']) {
const token = getCookieFromBrowser(authCookieName)
headers = { ...headers, 'Auth-Token': token }
}
return ({ headers })
})
So if the header is already present in the previous context (which is the case when sent from the server), just use it. If it is not present (when sent from the browser), get the cookie from the browser and set it.
I hope it will help somebody one day.
I have an app where most of the endpoints use the same token to authenticate. So, when a user logs in I use the following:
axios.defaults.headers.common['Authorization'] = 'Bearer ' + user.access_token
But I have some endpoints that have a different Bearer token. In these cases, I'm trying this:
axios.get(`${API_BASE}/Config`, { headers: { Authorization: AuthStr } })
.then(response => {
if (response.status === 200) {
commit(HIDE_LOADING)
resolve(response.data)
}
})
Where AuthStr is being passed in as an argument and is the correct Bearer Token for this endpoint. But when I call this method, axios is sending the Bearer Token configured on axios.defaults.headers.common['Authorization'] and is ignoring my AuthStr token argument.
How can I override this?
As pointed out by #Maaz Syed Adeeb this is an axios bug. I could solve using the following code as suggested in: issue
axios.get(`${API_BASE}/EndPointThatUserAnotherToken`, getAxiosOptions(AuthStr))
.then(response => {
if (response.status === 200) {
commit(HIDE_LOADING)
resolve(response.data)
}
})
function getAxiosOptions (authToken) {
let opt = {
transformRequest: [function (data, headers) {
delete headers.common.Authorization
headers.Authorization = authToken
return data
}]
}
return opt
}