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.
Related
I made a Google Cloud function, but it returns data even when I type in the URL in an incognito window. How do I make my Google Cloud functions only available for myWebsite.com or localhost?
This is not possible to fully enforce. When you make an HTTP endpoint, you should expect that it could be accessed from anywhere, and that the access may have headers that do not match what a web browser would normally send.
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.
I am a long time programmer (C, Python, FORTRAN), but this is my first foray into javascript and anything web, so I am learning on the fly.
So, the main question up front: Can I use the google maps directions API from a script section of a simple web page on my laptop, or does it need to be called from a server?
I have an API key and I have successfully used parts of the API that are called as functions (Map, Geometry). I am trying to use the google maps directions API, which as I understand it, you must use via a URL and an HTTP GET. Here is a sample URL that my code has constructed:
https://maps.googleapis.com/maps/api/directions/json?origin=45.0491174%2C-93.46037330000001&destination=45.48282401917292%2C-93.46037330000001&key="my key"
If I paste that URL into the address bar, it works. I get a document back with the directions info. If I execute it from inside a script section on a simple web page I am building, the response I get is:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
I did some searching, both in stackoverflow and elsewhere on the web and I came across this:
http://www.html5rocks.com/en/tutorials/cors/
Per that page, I checked to make sure that withCredentials was supported and then I set withCredentials to true. This did not alter the outcome. Obviously, the API works, so I am now wondering if I have to do this from a web server and not from a simple web page to get around the cross-domain limitations. I am hoping to avoid having to set up a server since this is a one-off for my own personal use, but maybe I dont have a choice?
As an aside, does anyone have any insight into why the directions API is called via a URL rather than as a javascript function like many of the others?
For JavaScript better use the Web -> Maps JavaScript API. This helped me solve this issue without a server.
The problem is that your Web Services -> Directions API unlike e.g. the Web Services -> Geolocations API, does not provide JS XSS functionalities like server side access-control-allow-origin: * response headers or JSONP functionality. Maybe this is even a bug of Google because it seems very strange to me that one "Web Services" API server does allow JS XSS and another not.
See https://stackoverflow.com/a/26198407/3069376
To answer the main question, Yes. You can definitely use the GoogleMap Directions API inside your web page. To get you started quick and easy, follow this link . Then,
Click on the JAVASCRIPT + HTML version, copy the whole code and paste it into a text editor and save it as an html file.
Start your own local server (like node.js). Dont forget to obtain a Browser API key and set your HTTP refferer (example http://localhost:4567) in Google Developer Console or you will get errors.
Run your html file on your local server (example http://localhost:4567/myprojfolder/samplewebfile.html) .
You can do this with all Google Maps JavaScript API samples. If you're curious about setting a node.js server, there are plenty of resources online.
I'm trying to connect to the Expedia Api. With this they have an api key and id.
I was using jsonp with this but there is a bug in there causing problems. The other thing is my api key is exposed in the javascript.
So now I have to find another way. I am now requesting json but of course I can't get cross domain with it so I have found a php proxy. My app is now reliant on php (this is ok though). When I access the php proxy I now get authentication errors. I have tried a different endpoint on a different site and the script works.
So therefore I cannot access this API.
There seems to be very little information, tutorials and scripts out there on how to make an api cross site, php proxies or authentication. I thought with the amount of sites now reliant on this type of technology there might be something.
How can I make a php proxy and return this data back to angular?
How can I safely hide my api key?
Have all of your API keys etc in a PHP file on your server. In that PHP file you need to curl to the API. Then have your PHP script return a json_encode() of whatever their API returns. That way no one sees your API deets.
Is it possible to open sockets and get data from web in JavaScript.
My aim is: to work with web data using JS.
I have looked for XmlHttp/AJAX solution, but I have found one note, that AJAX can be used only for calling localhost programs, which will be used as proxy and then only returns data from web.
It's because of sandbox model in browsers, which don't allow to work with sockets/other sites from JavaScript, and it works only in localhost.
Are there any solutions with JS to work with other world?
Your issue is due to cross domain request security, where you can't asynchronously get data from a domain which doesn't match the current host (this includes subdomains). You can however use jsonp, but this relies on the service that you're quering to supply the data in a jsonp format (a function call with the json data as a response).
If you have no control over the services you're requesting (which i assume you don't), you can use a javascript library, such as YUI or jQuery to perform the cross domain request for you (which typically uses Flash as the data proxy). However this will only work if you the site in question allows cross domain requests from your domain (defined in crossdomain.xml).