Is there by any means one can access remote data using restful api without CORS enabled on the remote server.
I'm asking this because I'm trying to access a remote data via an API with angularjs and I've tried all my best can't get seem to load the data. I always get this from Chrome
No 'Access-Control-Allow-Origin' header is present on the requested resource
Below is my script
var auth = $base64.encode("dHNxdWFpbm9vOlFoYXNoZW0xMjM="),
headers = {"Authorization": "Basic " + auth};
$http({method: 'GET', url: 'http://mywebapp.com/Cust?account_number=010104051681',
headers: { 'Authorization': 'Basic dHNxdWFpbm9vOlFoYXNoZW0xMjM=' }
}).success
(function(data){
$scope.user=data;
console.log(JSON.stringify(data));
});
so without CORS enabled, its there a way I can get the data via JS or unless I enable CORS I can't get the data
You can make a reverse proxy https://en.wikipedia.org/wiki/Reverse_proxy. In short:
AngularJS client calls Your backend server
Your backend server calls http://mywebapp.com/Cust?account_number=010104051681
Your backend server get response
Your backend server sends that response back to the AngularJS client.
Related
I'm trying to build a website that requests JIRA data from a company-owned JIRA Board via REST API and displays the requested data in different graphs. While developing with JavaScript I ran into the CORS header 'Access-Control-Allow-Origin' missing error and therefore could not access the data.
Here is some code:
var url = myUrl;
var auth_string = myJira_user + ":" + myJira_password;
var encoded_string = btoa(auth_string);
var http_headers = {
"Content-Type": "application/json",
Authorization: "Basic " + encoded_string
};
var headers = new Headers(http_headers);
fetch(url, headers)
.then(response => {
return response.json();
})
.then(data => {
console.log(data);
})
.catch(err => {});
This JS script throws the above-mentioned error in my browser console, while a simple python script or curl command with the same parameters works and outputs data. How is that possible?
Modern browsers first check CORS policy on the API server via an HTTP OPTIONS call. This is known as "preflighting a request".
CORS: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
HTTP OPTIONS: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS
In effect, the browser first checks with the API server whether it has permission to call and consume APIs from the origin (website where the user is browsing from, identified by domain, protocol, and port). If the API server expects calls to be made from the origin, it returns a success response to the OPTIONS calls and then the browser proceeds to make the GET/POST/etc call. However, if the API server does not recognize the origin from the OPTIONS call, it will return a fail response, and the browser will not proceed with the API call and instead generates the exception you've observerd.
CORS + HTTP OPTIONS is one mechanism in the arsenal of securing API access and mitigating the plethora of security and privacy issues arising from Cross-Site-Scripting.
But to your point, CORS does not impact calls made from non-browser applications. A non-browser application, such as CURL or any code you can write in Python, Node, etc. does not make the OPTIONS calls and therefore, the API server's CORS policies do not apply.
You could setup a middleman/proxy server that receives API requests from your web application, call the target API server, and marshal back the response, therefore circumventing the CORS policy.
I want to make some API requests to the shipping carriers at the BigCommerce product page and I have some credential for that requests which I don't want to show in my JS code. According to the specific environment of BigCommerce I can't make any changes in back end code. I read a lot of similar questions and now have only one question.
Is it only one way to do that using my own API back end web-server which will store credential information and send POST request to the third party API? Then I will receive that information using a POST request via JS to my own API.
I have tried to run Ruby API application on the nginx web-server. However, it was unsuccessful because browser blocked my fetch() request according to the CORS Policy. I tried to add Access-Control-Allow-Origin: * parameter to the server response header writing it in ruby config file but browser didn't recognize it. Also I tried to set up configuration file on the nginx side but that didn't help me with CORS policy response. That's interesting because using Restlet Application I received response from my own API application with correct information and status "ok".
(async function application() {
let dataRuby = {
url: 'http://IP_address/index',
body: {"name": "21312", "year": "2019"}
};
function getApi(data) {
let myInit = {};
myInit.method = "POST";
myInit.body = JSON.stringify(data.body);
myInit.headers = {
'Content-Type': 'application/json'
};
let myRequest = new Request(data.url, myInit);
return fetch(myRequest).then(
res => res.json()
);
}
let response = await getApi(dataRuby);
console.log(response);
})()
Access to fetch at http://IP_address/index from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I have just followed the steps which were given in the Jenkins website. Now I can login into Jenkins using http://localhost:8080
When I use http://localhost:8080/api/json?pretty=true I can get JSON response from my localhost server. But when I try to get the data to a html page i.e., when I use url http://localhost:1234/foldername/file.html I'm unable to get the data using AJAX call. Below is the code I'm using for AJAX Call
$.ajax({
type: 'GET',
url: 'http://localhost:8080/api/json?pretty=true',
dataType: 'json',
//whatever you need
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', make_base_auth('admin', 'admin'));
},
success: function (data){
alert(data);
}
});
function make_base_auth(user, password) {
var tok = user + ':' + password;
var hash = btoa(tok);
return 'Basic ' + hash;
}
I'm getting an authentication error.
From my understanding of the documentation, Jenkins recommends using your user's API key provided via HTTP Basic Authentication, not its password.
Modern jQuery (1.5 or later) also has added a headers field to the options for jQuery.ajax()
headers: {'Authorization': 'Basic ' + btoa('username:apitoken')}
However, what you describe here should do fine without these suggestions.
My assumption is that you are running into the Same-origin policy since your client is based in a browser document, from a different origin (different port) than your Jenkins server runs on. You will need to add CORS headers on your Jenkins server allowing your page's domain access to Jenkins resources, or have both Jekins API + your client page hosted from a single origin.
For your example here, you could use the CORS Filter Plugin and would need to add headers at least as permissive as follows:
Access-Control-Allow-Origins: http://localhost:1234
Access-Control-Allow-Methods: GET, OPTIONS
Access-Control-Allow-Headers: Authorization
In production, you could either use a single origin, or update the list of origins to include wherever your dashboard lives in production, or if you're confident about Same-origin problems, * as a wildcard for any origin.
I can't execute the 'GET' request with the getTasks() function.
$(document).ready(function(){
getTasks();
});
const apiKey = 'xxxxxxx';
function getTasks(){
$.ajax({
type: 'GET',
url: 'https://api.mlab.com/api/1/databases/taskmanager/collections/tasks?apiKey='+apiKey,
contentType: 'application/json',
xhrFields: {
withCredentials: true
},
success: function(data){
console.log(data);
},
error: function(){
console.log('FAIL')
}
})
}
The error that I get is:
api.mlab.com/api/1/databases/taskmanager/collections/tasks?apiKey=xxxxxxx
Failed to load resource: the server responded with a status of 400
(Bad Request)
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access. The response
had HTTP status code 400.
I understand that Google-Chrome on Windows is CORS enabled, and will not (by default) allow communication with a different domain. I'm not sure what a preflight request is. Regardless, I tried to implement what I saw from Using CORS - HTML5 Rocks (from the CORS from jQuery section), but to no avail.
At a guess, the remote API simply does not respond to pre-flight requests for GET calls (because it shouldn't have to).
Your code is triggering a pre-flight request because it is non-simple. This is due to your adding a Content-type: application/json header. A request Content-type header is used to indicate the request payload format. As it is a GET, there is no payload.
Try this instead...
$.getJSON('https://api.mlab.com/api/1/databases/taskmanager/collections/tasks', {
apiKey: apiKey
}).done(function(data) {
console.log(data)
}).fail(function() {
console.log('FAIL')
})
CORS is there to protect you. If you want some more info on it, wikipedia has a good entry on it.
It appears the issue here is that you're trying to access your mongodb hosted by mlab directly from your web app. As you can see in your code, you're providing credentials/api keys to make that request.
My guess is that mlab's intent of not allowing CORS is to prevent you from doing this. You should never put your private API keys in html to be hosted on a web page, as it's easily accessible by reading source code. Then someone would have direct access to your mongodb.
Instead, you should create a server-side application (node, or... ** Whatever **) that exposes an api you control on the same domain (or a domain you give permission to via CORS).
As far as the "preflight" request, if you look in your chrome debugging tools, you should see an additional request go out with the "OPTIONS" method. This is the request that chrome (and most other http clients) send out first to a server hosted on a different domain. it's looking for the Access-Control-Allow-Origin header to find out whether it's allowed to make the request. Pretty interesting stuff if you ever have some time to dig into it.
I am trying to get data from API that has oAuth authentication.
What I am doing is sending the auth request from server1 (where my Angular app is) to server2 and I get the access token. Then I put the token in the JS variable and I am trying to access an API endpoint.
My js code looks like this:
let headers = new Headers({ 'Authorization': "Bearer " + oAuthAccessToken });
let options = new RequestOptions({ headers: headers });
let url = "http://example.com/api/getSomething"
this.http.post(url, body, options)
.subscribe( res => {
console.log(res.json())
});
The problem is that I am always getting "401 Unathorized". When I inspect the request in the Network tab of Chrome Dev Tools I see two strange things - first the request method is OPTIONS not POST and the header Authorization is missing.
Any idea what I might be doing wrong ? Why is the header not set ?
Edit:
The problem was that Angular sends OPTIONS request before the POST and my app firewall was expecting Authorization header to be always present. This header is not present in the OPTIONS request so I was getting Unauthorized. I changed my server app to send proper headers on OPTIONS request and now everything is fine.
Thanks for the help.
I think the browser try to discover which http methods are allowed, so the first request is an request with the OPTIONS method. Usually the backend service answers with Access-Control-Allow-Methods inside the header. Afterwards the browser sends the real request.
I think that you need to allow CORS, then it should work as expected
As you are dealing with cross-domain requests, Chrome is preflighting the request to look for CORS headers. If the request is acceptable, it will then send the real request. so the option request is just to check is the server support CORS.
From : https://stackoverflow.com/a/21783145/3279156
Content-Type should be like below:
let header= new Headers({'Content-type':'application/x-www-form-urlencode'});
header.append('Authorization',"Bearer " + token);
let opt= new RequestOptions({headers:header});