Axios not setting default headers in app.js when logged in - javascript

The issue I am having is when trying to make a POST request I keep getting "Unauthenticated" error. This issue is because the api_token is not being passed.
If I make this request using PostMan it works.
Inside app.js I did a console.log(axios.defaults.headers.common) and that returns me the X-CSRF-Token & Authorization Bearer xxxx token.
Although, right before the axios call on the website (after submit), I added another console.log(axios.defaults.headers.common) and the only thing returned is Accept: 'application/json, text/plain, */*' which explains why the "Unauthenticated" error comes in, although I can't figure out why its correct in app.js but nothing get's passed after the fact. NOTE: I did not re-import axios in my component.
Inside my app.js file I have preset the headers for axios:
window.axios = require('axios')
let token = document.head.querySelector('meta[name="csrf-token"]');
if (token) {
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
}
let api_token = document.head.querySelector('meta[name="api-token"]');
if (api_token) {
console.log('api_token.content',api_token.content )
// THIS ABOVE RETURNS DATA CORRECTLY.
window.axios.defaults.headers.common['Authorization'] = 'Bearer ' + api_token.content;
}
Website - component after submit:
async submitForm () {
console.log('window.axios.default.headers.common', axios.defaults.headers.common)
// THIS ABOVE ^^ RETURNS EMPTY HEADERS
const res = await axios.post('/api/product/add/validate', this.form)
}

Related

How to set axios header dynamically according to access_token expired and url

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
}
})

issue with making a call using fetch and jwt

*My goal here is to get the location of bikes from a bike-sharing company's API.
I did Steps 1 and 2 using Postman. but ill try to integrate it into my code once I get the hang of it.
The first step is to verify your email and generate an Auth token. This requires only a verifiable email address. Make a POST request to https://web.spin.pm/api/v1/magic_links with the body:
{"email": "sampleemail#gmail.com"}
From there, you will need to find the token within your email. This token needs to be sent with a POST request to
https://web.spin.pm/api/v1/auth_tokens with the body:
{
"grant_type": "magic_link",
"magic_link": {
"email": "<email>",
"token": "<token>"
}
}
This request returns a JSON that looks like this: {"jwt":"eyJ0eXAiOiJ.....cXVLw","refreshToken":"2cb07....bab5030","existingAccount":false}
To get the position of vehicles so a GET-Request to https://web.spin.pm/api/v3/vehicles?lng=-77.0146489&lat=38.8969363&distance=&mode= User Header Authorization: Bearer to Authenticate and use the jwt-Token we got from the Auth request.
You will get something like this as return JSON {"vehicles":[{"lat":37.69247,"lng":-122.46595,"last4":"3595","vehicle_type":"bicycle","batt_percentage":null,"rebalance":null}, … ]}
Step 3 is done using (async/awit function) using fetch where I am having the problem with. I copy-pasted the jwt in my .env file and set up the proper headers.
I get a 401 response when making the call. when I tested step 3 using postman everything seems to work fine.
I have attached a screenshot of the error in this post. Hopefully its more clear, Thanks in advance.
const fetch = require("node-fetch");
require('dotenv').config();
async function getBikes()
{
const lat = '38.897574612438575';
const lng = '-77.01855164084469';
const api_url = `https://web.spin.pm/api/v3/vehicles?lng=${lng}&lat=${lat}&distance=&mode=`;
const jwt_key = process.env.BERER_KEY;
try{
const config = { method: 'GET',
headers: {json: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer'+ jwt_key
} },
rejectUnauthorized: false
};
const response = await fetch(api_url,config );
const data = await response.json(); //response.json() //headers //.jwt; //response.json()
if (response.ok)
{
console.log("STATUS CODE IS: "+response.status);
console.log('My JWT:', response);
return data;
}
else{
console.log("something went wrong ");
console.log("STATUS CODE IS: "+ response.status);
console.log( response);
}
} catch (error) {
console.log(error);
}
}
const y = getBikes();
console.log(y)
BEARER_KEY=eyJhbGciOiJIUzI1NiJ9.eyJ1c2V

Reddit API /api/me unable to make it work

I managed to get Reddit OAuth to work and it is getting redirected to my homepage.
And I am getting a URL like http://localhost:3000/?state=XEA12&code=6p4pAyle2EWGVwIBlFJ6ERXjxKg
Now, when I try other APIs like /api/me. I am not able to get it working. I have also set the scope of my app to identity.
Here is the code snippet that I wrote:
import axios from "axios";
import useSWR from "swr";
const link = "https://www.reddit.com/api/v1/me";
const config = {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
Authorization: "bearer 6p4pAyle2EWGVwIBlFJ6ERXjxKg",
},
};
const fetcher = (url) => axios.get(url, config).then((res) => res);
export default function Home() {
const { data, error } = useSWR(link, fetcher);
if (error) return <div>failed to load </div>;
if (!data) return <div>loading...</div>;
return <div>{JSON.stringify(data)}</div>;
}
Can you please tell me what I am doing wrong? Is it because of the headers or do I need to pass something else?
According to the documentation you need to retrieve access_token first, by using code param. Here is how to do that: https://github.com/reddit-archive/reddit/wiki/OAuth2#retrieving-the-access-token
Then you can use that access_token in a bearer auth. There is another note: API requests with a bearer token should be made to https://oauth.reddit.com, NOT www.reddit.com. Hope it will help

Invalid API Token

I am pretty new to CORS. I am building a React App which simply posts data to a backend API. According to the API documentation I have to send a BASIC Authentication Header along with the request which is exactly what I am doing. The request works just fine when I send it through POSTMAN. But when I make the same request from my APP it says Invalid API Key. Below is my code:
App.js:
import React from 'react';
class App extends React.Component{
state = {
data: 'data'
};
handleClick = async () =>{
const res = await fetch('https://myapi.com/post',{
method: 'POST',
body: JSON.stringify({tp:'0'}),
mode: 'cors',
headers: {
content-type:'application/x-www-form-urlencoded',
Authorization : 'Basic ' + new Buffer('username:password').toString(base64)
}
});
const data = await res.json();
this.setState({data});
}
render() {
return(
<div>
<p>{this.state.data}</p>
<button onClick={this.handleClick}>Post</button>
</div>
);
}
}
I looked into the issue and found out that the headers are not being set when sending the request. When further digging into it I found out that the above request is not a simple request and hence the browser makes a preflight OPTIONS request to server. I do not know how the server is handling the requests but I think the server is not configured to handle the preflight OPTIONS. I might be wrong. I do not have any access to the server code. The same request through CORS Anywhere proxy and POSTMAN client is working fine but not while using the actual app. I used create-react-app to setup the boilerplate.
All I get is an Invalid API Token Error while sending request through the app.
Any help on how to get the headers through to the server would be appreciated.
According to another post, you might want to wrap the Authorization header in a Headers-object. I guess you should not really pay attention to the OPTIONS-request, that request shouldn't contain any user credentials and the server shouldn't really look for any credentials on a OPTIONS-request, more info.
What happens if you make the following changes (don't forget to npm install base-64).
import React from 'react';
const base64 = require('base-64');
class App extends React.Component{
state = {
data: 'data'
};
handleClick = async () => {
const headers = new Headers();
headers.append("Authorization", "Basic " + base64.encode("user:password"));
const res = await fetch('https://myapi.com/post',{
method: 'POST',
body: JSON.stringify({tp:'0'}),
mode: 'cors',
headers: headers
});
const data = await res.json();
this.setState({data});
}
render() {
return(
<div>
<p>{this.state.data}</p>
<button onClick={this.handleClick}>Post</button>
</div>
);
}
}

Javascript Test - Verify if Authorization header is correct using axios

I'm using an axios interceptor to set the Authorization token in requests headers.
axios.interceptors.request.use(config => {
config.headers.Authorization = 'Bearer ' + Auth.getToken()
return config
})
How can i test if my requests are sent with correct token in header?
Ps.: I'm using Mocha + Chai
Use axios-mock-adapter to mock Axios, and get the request information from the config object in:
.reply((config) => {})
Example:
import MockAdapter from 'axios-mock-adapter'
const axiosMock = new MockAdapter(axios)
axiosMock.onGet('https://api.com').reply((config) => {
return [200, { requestHeaders: config.headers }]
});
const response = await axiosWrapper.get('https://api.com')
expect(response.data.requestHeaders['Authorization'] === 'AUTH_TOKEN')
To test if the correct token is in the header, an integration test would be more approriate. When the correct token is in the header, the API response should be different than when an incorrect token is sent with the request to the API.
If would like to test your headers in the response you could do something like this:
const mock = new MockAdapter(axios);
mock.onGet('/anon/getUser').reply(200, {/*response.data*/}, {'my-header-key': 'my-value' });

Categories