I am trying to get data from a AWS endpoint using React/axios, but when I try to make a request I get this CORS error:
Access to XMLHttpRequest at 'https://myAWS.com/login' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
when I try on my hosted github pages build, I also get the same error. But when I use Vanilla js on another hosted website it works, am I sendig my requests wrong on axios?
VANILLA
let body = {
"name": "Bbbb 202",
"email": "bbbb2220#bob.com",
"password": "122",
"wallet": "bbbbB202222"
};
var http = new XMLHttpRequest();
var url = 'https://myAWS.com/login';
http.open('POST', url, true);
//Send the proper header information along with the request
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
http.onreadystatechange = function() {//Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(body);
REACT
async SendRequest(method, url, callback, body){
axios.request({
method: 'POST',
data: JSON.stringify(body),
headers: {
"Content-Type": "application/json;charset=utf-8",
"Authorization": "Bearer " + localStorage.getItem("token"),
},
url: url
})
.then(response => {
console.log(response);
callback({
status: response.status,
data: response.data,
});
})
.catch(err => {
console.log(err);
callback({
status: err.status,
data: err,
});
});
}
These are not the same request. The 'vanilla' request looks like it might qualify for what's known as a 'safe request'. To qualify as a safe request, content-type must be application/x-www-form-urlencoded (or 2 others), and not use any restricted HTTP methods.
I wrote more extensively about it here as well: https://evertpot.com/no-cors/
Related
I have a frontend running on HTTPS locally with a local certificate. I'd like to hit a local backend that is on HTTP.
I added the meta tag to my index.html to allow for this:
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
...but axios refuses to do it:
axios({
method: 'post',
baseURL: 'http://localhost:3000',
url: '/test',
data: {
firstName: 'Will',
lastName: 'Smith'
}
}).then((result) => {
console.log('done!');
}
Note that I explicitly add http to the baseUrl. Still, I get this:
POST https://localhost:3000/test net::ERR_SSL_PROTOCOL_ERROR
Axios still sends through https.
I tried using fetch:
fetch('http://localhost:3000/test', {
method : "POST",
body: JSON.stringify({
firstName: 'Finn',
lastName: 'Williams'
}),
}).then((response) => {
console.log('done! ' + response.json());
).catch((error) => {
console.log('error');
});
Then finally a raw XMLHttpRequest request:
const http = new XMLHttpRequest();
http.open("POST", 'http://localhost:3000/test', true);
// Call a function when the state
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
alert(http.responseText);
}
}
http.send(JSON.stringify({
firstName: 'Finn',
lastName: 'Williams'
}));
But every time the browser seems to switch to HTTPS and it fails with that same error.
Is it possible to make this happen?
It's not possible due to Same origin policy. Or you can have a server side solution to redirect https requests to http.
I'm trying to execute query using REST API, in a lightning web component.
the request in Postman returning result with success (enabling Follow Authorization header)
but in the JavaScript in lightning web component it returns 401 Unauthorized
the code in the java script is a follow :
let sessionId = 'tokken';
let baseUrl = window.location.origin;
let header = {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": "Bearer " + sessionId,
};
if (sessionId) {
let options = {
method: "GET",
mode: 'no-cors',
redirect: 'follow',
headers: header,
};
fetch(baseUrl + '/services/data/v50.0/query/?q=SELECT+name+from+Account', options).then((response) => {
console.log(JSON.stringify(response));
if (!response.ok) {
// throw Error(JSON.stringify(response));
} else {
return response.json();
}
}).then((repos) => {
console.log(repos, repos);
});
}
am I missing something ?
Since you can not pass the value Authorization to no-cors mode, you will need to add CORS configuration in your SalesForce as safe endpoint where they let you make a call.
You can not send Authorization header with "no-cors" mode.
mode: "no-cors"only allows a limited set of headers in the request:
Accept
Accept-Language
Content-Language
Content-Type with a value of application/x-www-form-urlencoded, multipart/form-data, or text/plain
I am not able to receive the resources from an API using different functions in javascript.
It works as follows:
In one tab of the browser I open the application webclient and receive a cookie for that domain:
first_browser_tab
In another tab I open a page of a different domain and using javascript I request the ressource from the API. It runs over a gateway which has the same domain as my endpoint:
second_browser_tab
The cookie is not sent in the request and for this reason I get an authentication error from the endpoint to my request.
I tried to send the request in different ways and it allways fails due to the endpoint authentication.
See the code:
Using fetch
const urlToApiFetch = 'https://app.apple.com/api';
fetch(urlToApiFetch, {
method: "GET",
mode: "cors",
credentials: "include",
headers: {
"Authorization": "Bearer 12345",
"x-api-key": "12345",
}
})
.then((response) => {
console.log(response);
})
.catch ((error) => {
console.log(error)
});
Using XMLHttpRequest
const urlToApiXMLHttpRequest = 'https://app.apple.com/api';
let testUrl = urlToApiXMLHttpRequest;
let xhr = new XMLHttpRequest();
xhr.open("get", testUrl, true);
xhr.setRequestHeader("Authorization", "Bearer 12345");
xhr.setRequestHeader("x-api-key", "12345");
xhr.withCredentials = true;
xhr.onreadystatechange = function(r) {
console.log(r);
}
xhr.send();
Using jQuery
const URL = "https://app.apple.com/api";
$.ajax({
url: URL,
crossDomain: true,
method: "GET",
xhrFields: {
withCredentials: true
},
headers: {
"Authorization": "Bearer 12345",
"x-api-key": "12345",
}
}).done(function(data, status){
console.log(data);
console.log(status);
}).fail(function(data, status){
console.log(data);
console.log(status);
});
Does anyone have an idea on what is wrong? Why does the cookie is not sent?
Thanks a lot
I found the issue...
The response header was missing the parameter:
Access-Control-Allow-Credentials: true
More details here: https://javascript.info/fetch-crossorigin
Couldn't find any documentation on this, so before I dig deep in code does anyone out there know how to use basic authentication when making a REST request using 'fetch' (https://github.com/github/fetch).
Just tried the following line, but the header was not set in the request:
fetch('http://localhost:8080/timeEntry', {
mode: 'no-cors',
headers: { 'Authorization': 'Basic YW5kcmVhczpzZWxlbndhbGw=' }
})
.then(checkStatus)
.then(parseJSON)
.then(function(activities) {
console.log('request succeeded with JSON response', data);
dispatch(activitiesFetched(activities, null));
}).catch(function(error) {
console.log('request failed', error);
dispatch(activitiesFetched(null, error));
});
The username and password is my own first and last name, using curl it works.
If I put { 'Accept' : 'application/test' } Accept is set, just not Authorization... strange.
Just for me to able to continue I added credentials: 'include' which makes the browser to prompt for username and password which is used for communicationg with the REST backend. Just for testing, will use OAuth further on.
fetch('http://localhost:8080/timeEntry', {
mode: 'no-cors',
credentials: 'include'
})
.then(checkStatus)
.then(parseJSON)
.then(function(activities) {
console.log('request succeeded with JSON response', data);
dispatch(activitiesFetched(activities, null));
}).catch(function(error) {
console.log('request failed', error);
dispatch(activitiesFetched(null, error));
});
no-cors mode prevents the headers from being anything other than simple headers.
"Authorization" header doesn't fit to simple headers. See more here: https://developer.mozilla.org/en-US/docs/Web/API/Request/mode
Note that if you use fetch with Authorization header you will NOT establish a session. You will have to manually add that header for every request. Navigating to secured path would also not be possible.
So to make this work You should pre-authenticate with XMLHttpRequest. You can do this like so:
var authUrl = location.origin + '/secured-path/';
var http = new XMLHttpRequest();
http.open("get", authUrl, false, login, pass);
http.send("");
if (http.status == 200) {
//location.href = authUrl;
} else {
alert("⚠️ Authentication failed.");
}
Note that above is synchronous so you don't need a callback here.
So after doing this you can use fetch without headers e.g. this request should be successful:
fetch(authUrl, {
method: 'get',
}).then(function(response) {
console.log(response);
});
Since it looks like the library you are using is a polyfill for Fetch API, I'm going to work off of the assumption that the syntax should carry through as well.
The samples I found on Mozilla's page indicate that the fetch method signature is fetch('API_ENDPOINT', OBJECT) where object looks like:
myHeaders = new Headers({
"Authorization": "Basic YW5kcmVhczpzZWxlbndhbGw="
});
var obj = {
method: 'GET',
headers: myHeaders
})
So the method becomes:
fetch('http://localhost:8080/timeEntry', obj)
.then(checkStatus)
.then(parseJSON)...
I have not tested this code, but it seems consistent with what I was able to find. Hope this points you in the right direction.
I'm encountering an issue while trying to retrieve an access token using the Strava API: https://strava.github.io/api/v3/oauth/
My initial code request and callback function properly, but when attempting to hit the /oauth/token URL I fail in two different ways. The first:
console.log('Posting to /token with code: ' + code);
Ember.$.ajax({
type: 'POST',
url: 'https://www.strava.com/oauth/token',
data: 'client_id=<myid>&client_secret=<mysecret>&code=' + code,
success: function(data) {
var jsonData = JSON.stringify(data);
var accessToken = jsonData.access_token;
console.log('Received access token: ' + accessToken);
if (accessToken) {
this.get("controllers.application").set('settings.strava.accessKey', accessToken);
}
},
error: function(jqXHR, textStatus) {
console.log('API auth error occurred: ' + JSON.stringify(error));
throw new Error(error);
}
});
Prints Posting to /token with code: 3ae248f... and the HTTP request comes back with a 200 response (in the Chrome debugger Network tab), but I can't actually see the response contents/data in the debugger, and the browser console complains with:
XMLHttpRequest cannot load https://www.strava.com/oauth/token. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:4200' is therefore not allowed
access.
But then if I add a few options to my above request:
crossDomain: true,
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'DELETE, HEAD, GET, OPTIONS, POST, PUT',
'Content-Type': 'application/json;charset=UTF-8'
},
Then an OPTIONS request goes out first (to the /oauth/token endpoint), and comes back with 302 Found, but I then see a different error in the browser console:
XMLHttpRequest cannot load https://www.strava.com/oauth/token. Response for preflight is invalid (redirect)
CORS is not something I have a huge amount of experience with, this is where I have run out of ideas.
The following works fine in my Cordova App:
var c_id = "YOUR_ID_HERE";
var c_secret = "YOUR_SECRET_HERE";
var access_code = "YOUR_AUTH_HTTP_CODE_HERE";
var params = "client_id=" + c_id + "&client_secret=" + c_secret + "&code=" + access_code;
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert(xmlhttp.responseText);
}
}
xmlhttp.open("POST", "https://www.strava.com/oauth/token", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.setRequestHeader("Content-length", params.length);
xmlhttp.setRequestHeader("Connection", "close");
xmlhttp.send(params);
For the preflight requests response should ends up with status 200 Ok and contains at least Access-Control-Allow-Origin: your origin