can somebody explain to me why when I am using fetch and accessed my nodejs api - it is authorized but when I tried using axios to access my api - it is unauthorized.
This is the code I am using in fetch (It came from tutorial: https://medium.com/#alexanderleon/implement-social-authentication-with-react-restful-api-9b44f4714fa) Bec I am studying his way of authenticating using passport-facebook-token.
(client -->(login fbsdk)--> fb --> (access token)--> client -->(pass access token)--> nodejs api --> (get credentials) --> passport-fb-token --> (send credentials) --> nodejs api --> (credentials)--> client)
const tokenBlob = new Blob([JSON.stringify({access_token: response.accessToken}, null, 2)], {type : 'application/json'});
const options = {
method: 'POST',
body: tokenBlob,
mode: 'cors',
cache: 'default'
};
fetch('http://localhost:4000/api/v1/auth/facebook', options).then(r => {
const token = r.headers.get('x-auth-token');
r.json().then(user => {
if (token) {
this.setState({isAuthenticated: true, user, token})
}
});
})
This is the code of my axios
axios({
method: 'post',
url: 'http://localhost:4000/api/v1/auth/facebook',
headers: {
'Access-Control-Allow-Origin': '*',
},
data: {
access_token: response.access_token
}
})
.then((res) => console.log(res))
.catch((err) => console.log(err));
You should configure axios to use your token in one central place. For example
export const configureAxios = (token) => {
axios.interceptors.request.use(req => {
// don't give our token to non-our servers
if (isDomesticRequest(req.url)) {
req.headers.Authorization = `Bearer ${token}`;
}
return req;
});
}
This blog should help you get your answer in detail:
Fetch vs. Axios.js for making http requests
Axios is a Javascript library used to make http requests from node.js
or XMLHttpRequests from the browser and it supports the Promise API
that is native to JS ES6. Another feature that it has over .fetch() is
that it performs automatic transforms of JSON data.
If you use .fetch() there is a two-step process when handing JSON
data. The first is to make the actual request and then the second is
to call the .json() method on the response.
The .fetch() method is a great step in the right direction of getting
http requests native in ES6, but just know that if you use it there
are a couple of gotchas that might be better handled by third-party
libraries like Axios.
Related
Postman Screenshot of dot net core API
Postman fetches the data from my dot net core API but I cannot get the data in React native using the same API. I tried everything like changing port number etc.
React Native API Request
useEffect(() => {
const getData= async () => {
try {
const response = await axios.get('http://10.0.2.2:54669/DoctorMaster/Getalldoctorssearch/1062');
setAppointments(response.data);
setIsLoading(false);
console.log(response.data);
} catch (error) {
console.log(error);
}
}
getData()
}, [setAppointments, setIsLoading]);
Please follow the below structure
fetch(
"url"
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: "Bearer " + JSON.parse(token),
},
}
)
.then((response) => response.json())
.then((responseJson) => {
// Handle response here
})
.catch((error) => {
console.error(error);
});
Be aware that React Native refuses HTTP requests instead of HTTPS requests by default:
To handle HTTP requests in Android see this post
To handle HTTP requests in iOS see this post
You are trying to fetch data from localhost which your mobile device won´t be able to fetch the url. You need to publish your API on a Web Server, and then you will be able to fetch the data
Solution: All of the answers did not work for me, I used a visual studio extension called Conveyor by keyoti to solve the issue, this extension allow me to use the API outside of localhost, it will show you the remote URL, use that url to call API from your mobile application
There were similar discussion here Firebase API doesn't respond with common error codes using Axios on react native, but guy was using Axios. I would like to use Fetch API, and hope there are similar solution using this API for current case.
The issue is when I get error from Firebase REST API statusText of response is empty. I only got status code.
If I will make same request with the same url and options using Axios I will get error description which defied by Firebase API (like TOKEN_EXPIRED, USER_DISABLED, USER_NOT_FOUND, INVALID_REFRESH_TOKEN, MISSING_REFRESH_TOKEN etc.) using console.log(error.response.data.error.message)
How I can achieve same output with Fetch API?
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: bodyString
});
if (response.ok) {
const payload = await response.json();
return payload as HttpResponse;
} else {
throw new Error(`Server error: ${response.statusText}. Status: ${response.status}`);
}
I don't know how I missed to check this.
The solution: await response.text()
The Firebase Documentation has some useful curl operations but doesn't provide information regarding Cors, headers, and auth using JS Fetch. We are using a fetch-only solution as I am creating a client-based Firebase npm package where users might not have the firebase modules imported for several reasons, tree shaking, minified project, etc.
I imagine I need to pass on the Auth as a header, What about Cors and credentials?
Here is a crude example, is this sufficient? or are there other unforeseen issues?
const pushOptions = {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
}
var dataAPI = await fetch(databaseUrl+`/test.json`,pushOptions)
.then(response => response.json())
Reference:
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
https://firebase.google.com/docs/reference/rest/database#section-put
The documentation says you need to pass your Firebase ID in query parameter 'access_token' and not in any header. For example,
curl 'https://[PROJECT_ID].firebaseio/users/jack/name.json?access_token=CREDENTIAL'
But I ended up getting Unauthorized errors.
However, the Authenticate with an ID Token section in Firebase Auth REST API documentation says, "pass the ID token generated above as the auth=<ID_TOKEN> query string parameter". A sample curl request for the same would be:
curl 'https://[PROJECT_ID].firebaseio/users/jack/name.json?auth=CREDENTIAL'
This request worked as expected.
About CORS, this answer says,
Firebase uses a fully-permissive cross-origin resource sharing (CORS) policy, meaning that you can make requests to the Firebase servers from any origin. This is possible because Firebase does not use cookies or traditional sessions to govern which requests are authorized and which are not.
Here's a working example using Javascript fetch:
firebase.auth().onAuthStateChanged(async (user) => {
const token = await firebase.auth().currentUser.getIdToken()
const pushOptions = {
method: 'GET',
}
const reqURL = "https://[PROJECT_ID].firebaseio.com" + `/path.json?auth=${token}`
const dataAPI = await fetch(reqURL, pushOptions)
.then(response => response.json())
.then(res => console.log(res))
})
I just used the client SDK to get an ID Token quickly but it will work irrespective of from where the token is generated - client SDK or Auth REST API.
The REST API accepts the same Firebase ID tokens used by the client SDKs.
I am writing an app in React-Native that makes a request to the Hubspot API. This has given me issues, as I initially attempted to make the request using the Node JS request module, which does not work with React Native when using Expo. I am now attempting to make the request to the Hubspot API with React Native's own Fetch API, but am having trouble translating my initial code written using the Node JS request module. I get an error when making a request to the Hubspot API. I've attached the two versions of the code to this question. Could anyone explain what is wrong with my translation of the Node JS code? Any advice would be much appreciated. Node JS version (request succeeds)
Fetch version (request fails)
Welcome to Stack Overflow :)
I think your fetch request is not written correctly. Instead of creating a new Request const you could pass all your params to the fetch function directly:
fetch('https://hubapi.com/whatever/CONFIDENTIAL', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
properties
})
})
.catch((error) => {
console.error(error);
});
Notice I also added a catch block at the end of the request. If it still fails you should at least get a better understanding of what exactly is failing.
The code I quoted above is taken from the React Native docs, link here. The docs contain a lot of great examples, including using a async/await and other networking libraries.
I tested it for you in my react native project. The request succeeds, of course I get This hapikey (CONFIDENTIAL) doesn't exist as response, because I don't have a key, but the query runs successfully:
try {
const response = await fetch(
'https://api.hubapi.com/contacts/v1/contact/?hapikey=CONFIDENTIAL',
{
method: 'POST',
headers: new Headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify({
"properties": [
{ property: 'email', value: 'test#email.com' },
{ property: 'firstname', value: 'Sean' },
{ property: 'lastname', value: 'Smith' },
]
})
}
);
const responseJson = await response.json();
console.log("response from hubapi:", responseJson)
} catch (e) {
console.error("Error on fetch request:", e);
}
I'm trying to get an OAuth token for the Reddit API following the Application Only OAuth instructions. My reddit app is an installed app, so for my grant_type I'm using https://oauth.reddit.com/grants/installed_client.
Currently I'm running a very short JS script to query the API and get a token:
const APP_ID = 'MY_APP_ID'
const DEVICE_ID = 'TRACKING_ID_20_TO_30_CHARS'
let form = new FormData()
form.append('grant_type', 'https://oauth.reddit.com/grants/installed_client')
form.append('device_id', DEVICE_ID)
fetch('https://www.reddit.com/api/v1/access_token', {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': `Basic ${btoa(`${APP_ID}:`)}`,
}),
body: form })
.then(handleResponse)
.then(function(data) {
console.log(data)
})
.catch(error => console.error(error))
function handleResponse(response) {
return response.json()
}
(Note: running the snippet as-is will give you a NetworkError because the APP_ID isn't a real one and I don't want to give mine out.)
The response I get is:
{
"error": "unsupported_grant_type"
}
When I try the same API request using a REST client I get back the expected response, so this makes me think that the problem is JavaScript-related. Since the grant_type matches what the instructions say I'm not really sure what to do with the error. I'm hoping someone else more experienced with OAuth will know what is going on here.
The problem was the use of the FormData object. In earlier stages of troubleshooting I found this answer on Reddit and decided to use it, but that didn't work for me.
It was submitting the data as multipart/form-data rather than application/x-www-form-urlencoded, which Reddit's OAuth server did not like. I wrote a helper function based on this answer which did the trick:
function urlEncode(data) {
let out = [];
for (let key in data) {
out.push(`${key}=${encodeURIComponent(data[key])}`);
}
return out.join('&')
}