No 'Access-Control-Allow-Origin' for public api request - javascript

I'm trying to perform an ajax request to a third party api from my web site using javascript (On the client side) and I receive a No 'Access-Control-Allow-Origin' error. When trying to access this from node.js project everything is working fine.
More over, when opening Chrome with --disable-web-security everything is working fine as well.
Any information about this issue will be appreciated :-)

You cannot access a third-party API without using CORS. CORS adds special headers (e.g. Access-Control-Allow-Origin) to the HTTP response. This makes sure, that the API can control which front-end can make a request to it. This means, however, your API needs to recognize your front-end URL and accept requests from it.
You can (a) use CORS on the API side (changes are necessary on the API) or (b) use your server-side language to make the API request (e.g. PHP makes the request to the API and the front-end receives the response from the PHP back-end). Everything else is prohibited by the browser's security settings.
You can read more about CORS e.g. here.

Related

Google Maps - calling the API directly from javascript vs using the SDK

I am trying to use the Google Places API from my javascript code.
(Assume that all the other things - api keys, enabling the API from google console, etc have already been done).
When I try to access the Places API directly from my javascript, it gives me a CORS error, which I presume is because my domain isn't whitelisted in the Places API.
To circumvent this, the suggested way is to use the Javascript Maps SDK.
The SDK is not an npm module, it is a hosted JS file which is in the same domain as the Places API.
What I am trying to understand is how can this SDK which is written in Javascript, make calls to the Places API and does not get the CORS error.
Does it have something to do with the fact that the Maps SDK and the Places API are served from the same domain?
Shouldn't these api calls be executed in the context of my domain and blocked due to CORS?
Would it still work if the SDK was a npm package?
The api call that the SDK makes is not exactly same as the Places API, but it is on the same domain.
/maps/api/place/autocomplete/json?input=Ben&key=KEY
vs
/maps/places/api/js/AutocompleteService.GetPredicitons
I have tried the /maps/places/api/js/AutocompleteService.GetPredicitons call directly from my javascript but it also gives me CORS error.
TL;DR; the google sdk is using jsonp, by making the call using a script tag and specifying a callback. This is different from a XHR request which is blocked by same origin policy.
Explanation:
Where the script is hosted does not matter, as it is executed in the context of your domain, so any api calls that the browser makes would have the origin as your domain and not the domain where the script is hosted.
Which means, if the SDK is calling an endpoint from maps.googleapis.com/maps/... , which it in fact does, the request should be made with origin as my domain, and should give CORS error, but it was still returning data.
On further inspection, I discovered that the SDK is not making an xhr request (Which is blocked due to same origin policy) , rather it is creating a script tag and processing the response returned by the server. It is doing that using jsonp, by providing a callback in the url, so that the server sends the response wrapped in that callback, and once the script is downloaded and executed, it runs the function and sdk can now process the data.
Some points about security and general understanding:
The sdk needs to have an api key, which it sends along with every api call. So, if you download the sdk from the hosted url by passing in your key (which looks something like this: https://maps.googleapis.com/maps/api/js?key=KEY&libraries=places) and distribute it, you would basically be distributing the sdk script which has your key hardcoded inside it. (Of course, that does not have any specific security implications if you have restrictions setup on your api key, which you should do as your key is otherwise visible to your users in the network calls)
Even after I understood that the sdk is working using jsonp, and i was able to make the exact same api call, when I changed the query text for which I needed suggestions and changed nothing else (all other parameters were the same), the call still failed with a 403. This is because, the sdk seems to send a token in the parameter which is somehow derived from the query text. So, it is not easy to just bypass the sdk and create those calls yourself, as for that you would need to figure out the token generation algorithm.
On top of this, since I have enabled Referer only api key security, so anyway google would not allow any other referer to use my key, even if the key is visible in the networks tab for the users of my application.

Power BI API Authentication

How can I call the Power BI API from my application and understand Microsoft APIs?
I have successfully authorized users via the Azure AD library for JavaScript. However I have not been able to get a successful response from the API in the console. I get an unauthorized error, no access control allow origin header is present on the requested resource.
I am used to making API calls using Javascript and Angular, but not with Microsoft APIs and how they must be authorized. I have tried to read articles but they go over my head.
The errors are as follows
Failed to load resource: the server responded with a status of 404 (Not Found)
XMLHttpRequest: cannot load https://api.powerbi.com/v1.0/myorg/dashboards. Response to preflight request doesn't pass access control check: No Access-Control-Allow-Origin header is present on the requested resource. Origin http://renniesb.github.io is therefore not allowed access. The response had HTTP status code 404.
nope
Repository with my project code
https://github.com/Renniesb/sample_dashboard/tree/gh-pages
Place in repository that shows my Power B.I API call https://github.com/Renniesb/sample_dashboard/blob/gh-pages/app/services/powerbi.service.js
Expected behavior
List dashboards in the console.
Test site
https://Renniesb.github.io/sample_dashboard. To test I authorize with my credentials. How would I let users of this forum test the behavior. How do I enable their credentials?
List of things I've tried already
Created a reverse proxy using the following website: http://shawnsimondeveloper.com/nodeproxyangular/
Used the JSONP hack to attempt to get around CORS problem.
Put in the origin of the call in the webconfig file.
Tested the site both locally and on a webpage on GitHub
You shouldn't need to use both CORS and the HTTP proxy. Since you are using the ADAL JS library it will automatically append your Power BI token to your outgoing HTTP requests.
You will also need to setup the following:
Enable implicit grant flow as described in Step 3
Also, the dashboards endpoint is still only available in the "beta" version. This was causing the 404's.
Update your URLs to https://api.powerbi.com/beta/myorg/dashboards
To continue to use standard AJAX call with CORS:
Update your Angular powerbiService service to make HTTP requests directly to the https://api.powerbi.com domain rather than relative urls.

Onedrive cors download in javascript

I'm trying to process onedrive files in client-side javascript, but first I need a way to use XMLHttpRequest to download the file. Onedrive supports cors for a lot of operations, but for downloading the file into javascript there is the following problem:
As mentioned here: onedrive rest api manual
I can send a request to:
GET https://apis.live.net/v5.0/FILE_ID/content?access_token=ACCESS_TOKEN
and it will reply with a location header redirecting the browser to the file. The problem is when I send these requests through XHR, the browser always sends the Origin header with the request. For the first request I described above, onedrive also replies with an Access-Control-Allow-Origin:* header, so the request is allowed in the browser. However, when the browser is redirected to the actual location of the file, that resource does not have the Access-Control-Allow-Origin header, so the XHR request is denied by the browser(chrome sends an Origin header set to null for the redirect request).
I've also tried getting the location but not redirecting automatically, and then sending another XHR request, this will set the origin header to the domain of my site, but the result is the same.
As I mentioned in the beginning, I need to process the data in javascript, so I'm not asking about how to download onedrive files to hard drive. I need the data to be accessible by javascript in the webpage.
I know that I can use server side programming to get the file data for me and then send it to the client, but for my application this is not an option(at least this is not what I'm asking for at the moment).
If there is no way to do this, does anyone have an idea why they would implement their api this way? To allow javascript to get the location through cors and redirect but not include a cors header for the redirected resource. Why not just deny cors in the first place? Is this a bug?
The answer, as best as I can tell, is that downloading content cannot be done purely by JavaScript in a browser. Why did they do it this way? You'd have to ask them, but I would guess either a bug, or some unspecified "security concerns". For what it's worth, they seem to think that downloading content is CORS compliant in the documentation here: https://dev.onedrive.com/misc/working-with-cors.htm:
To download files from OneDrive in a JavaScript app you cannot use the
/content API, since this responds with a 302 redirect. A 302 redirect
is explicitly prohibited when a CORS preflight is required, such as
when providing the Authorization header.
Instead, your app needs to select the #content.downloadUrl property,
which returns the same URL that /content would have redirected to.
This URL can then be requested directly using XMLHttpRequest. Because
these URLs are pre-authenticated they can be retrieved without a CORS
preflight request.
However, to the best of my knowledge, they are wrong. Just because you don't need a preflight request doesn't mean that the response is CORS-compliant. You still need an Access-Control-Allow-Origin header on the response.
For anyone wondering, this is still an issue in the new Graph API (which is essentially a proxy API to the OneDrive API, as I understand it). The same basic issue is still present - you can get a download URL from your items, but that URL points to a non-CORS-compliant resource, so it doesn't do you a whole lot of good.
I have an active issue open with Microsoft here about this issue. There has been some response to my issue (I got them to expose the download URL through the graph API), but I'm still waiting to see if they'll come up with a real solution to downloading content from JavaScript.
If I get a solution or real answer on that issue, I'll try to report back here so others in the future can have a real answer to reference.
This is not an answer, I cannot comment yet.
Last week the new API for onedrive was released. http://onedrive.github.io/index.htm
Unfortunately it will not solve the problem.
https://api.onedrive.com/v1.0/drive/root:{path and name}:/content?access_token={token}
Will still redirect to a ressource somewhere at https://X.files.1drv.com/.X.
Which will not contain any Access-Control-Allow-Origin headers. Same goes for the Url "#content.downloadUrl" in the JSON response.
I hope that microsoft will address this problem in the very near future, because the API is at the moment of very limited use, since you cannot process file contents from onedrive with html5 apps. Apart from the usual file browser.
The only solution, which I see at the moment would be a chrome app, which can process the Url without CORS. see https://developer.chrome.com/apps/angular_framework
Box does exactly the same thing for download requests. I have not found any way around this problem without involving a server because the browser will not let your program get access to the contents of the 302 redirect response. For security reasons I am not convinced of, browsers mandatorily follow redirect requests without allowing user intervention.
The way we finally worked around this was
the browser app sends the GET request to the server which forwards it to the cloud provider (box/ondrive).
server then DOES NOT follow the 302 redirect response from Box or OneDrive
The server instead returns to the browser app, the content of the location field in the 302 response header, which contains the download url
The javascript in the browser app then downloads the file using the url.
You can now just use the "#content.downloadUrl" property of the item in your GET request. Then there is no redirection.
From https://dev.onedrive.com/items/download.htm:
Returns a 302 Found response redirecting to a pre-authenticated download URL for the file. This is the same URL available through the #content.downloadUrl property on an item.

How to call a web api via ajax over SSL from a local html file?

I have a local html file in may desktop accessing a web api (JAX-RS) that responds with some JSON data. I enabled CORS and everything works fine, but only without SSL. How can I do to make it work with SSL? I use a self-signed certificate and can call this web api from a WPF application, but from a JavaScript application (standalone html file), when Chrome sends the OPTIONS pre-flight before the POST, the request seems not to even reach the server. I also tried to import the self-signed certificate in the browser, but nothing has changed.
The preflight request is not allowed to include an entity body or credentials. If you are using preflighted requests then you cannot use two way SSL.
The solution is to change the server to make the certificate optional. I've only done this using Apache HTTP server or Tomcat but I assume other servers are also capable of this.
In apache the setting should be changed to
SSLVerifyClient optional
and in Tomcat the SSL settings should be changed to
clientAuth="want"
Without this change only CORS simple requests will work.

Soap Ajax cross domain problem

I'm trying to access a SOAP web service on another server using ajax but I'm getting an Access Control Allow Origin error. The web service returns XML so JSONP can't be used and the web service is also being used in another app so modifications is probably the last option. Any solutions?
If you can't do JSONP, then your options are:
Craete a server proxy at the domain of the page that can fetch the desired result from the other domain and relay it to you from the allowed domain.
If you're willing to limit your browser support to some modern browsers, then you can investigate Cross Origin Resource Sharing (CORS) which is a "safer" way to do cross-domain requests. You can read about it here.
Cross-domain ajax support via Flash which requires the placement of an appropriate cross-domain policy file on the host of the server you want to access. See here and here for some more info.
You can set up a server proxy at the domain of the page.
This page would then call the soap web-service and give you back the response.
This page can then be called via ajax from ui.
Found the probably most easiest way by using Ajaxpro 2, of course it's meant for .NET. http://www.ajaxpro.info/
otherwise, jfriend00's suggestions are the next best options.

Categories

Resources