How to call Google API using CORS in Dynamics CRM

0

I have a simple call out to google API from a javascript webresource in Dynamics CRM 365.

            var xhr = new XMLHttpRequest();
        xhr.open("GET", 'https://maps.googleapis.com/maps/api/place/queryautocomplete/json?input={' + searchString + '}&types=address&language=en&crossDomain=true&key=[ourKey]', true);
        xhr.setRequestHeader('Access-Control-Allow-Origin', '*');
        xhr.setRequestHeader('Access-Control-Allow-Methods', 'GET,POST');
        xhr.onload = function () {
            var response = JSON.parse(xhr.responseText);

//do something with the response here

        };
        xhr.send();

I get the following messages and errors in dev tools in IE:

*SEC7118: XMLHttpRequest for https://maps.googleapis.com/maps/api/place/queryautocomplete/json?input={55 lllll}&types=address&language=en&crossDomain=true&key=[ourKey] required Cross Origin Resource Sharing (CORS). File: ClientApiWrapper.aspx

SEC7119: XMLHttpRequest for https://maps.googleapis.com/maps/api/place/queryautocomplete/json?input={55 lllll}&types=address&language=en&crossDomain=true&key=[ourKey] required CORS preflight. File: ClientApiWrapper.aspx

SEC7120: Origin http://[ourURL] not found in Access-Control-Allow-Origin header. File: ClientApiWrapper.aspx

SCRIPT7002: XMLHttpRequest: Network Error 0x80070005, Access is denied. File: ClientApiWrapper.aspx*

Looking through CORS related material and guides, I believe I've done everything right.

I've also tried this, albeit I expect a CORS issue here:
jQuery.post('https://maps.googleapis.com/maps/api/place/queryautocomplete/json?input={' + searchString + '}&types=address&language=' + langCode + '&key=[ourKey]', function (addresses) {
try {

//Do something with returned addresses here...

            }
            catch (e) {
                alert("AutoComplete ErrorInt: " + e.message);
            }
        });

I'm sure this is a Dynamics CRM related issue where dynamics doesn't play nicely outside it's own sandbox.

Can anyone please suggest a fix within the Dynamics CRM realm?

Thanks

cors
cross-domain
dynamics-crm
asked on Stack Overflow Apr 23, 2018 by Lindsay

2 Answers

1

The Access-Control-Allow-Origin and Access-Control-Allow-Methods headers are response headers, which are sent from the server in response to your request.

Just remove them completely from your xhr request code. The browser will add the Origin header for you (you do not specify it explicitly), and the server at maps.googleapis.com should add the required CORS response headers (Access-Control-Allow-Origin and possibly some others).

If you're still getting problems after that, post a full set of request and response headers for the GET request (and for the preflight OPTIONS request if there is one).

EDITED FOLLOWING COMMENTS

OK, so here's what I see from your comments (formatted):

var xhr = new XMLHttpRequest();
xhr.open("GET", 'maps.googleapis.com/maps/api/place/queryautocomplete/…{' + 
searchString + '}&types=address&language=en&crossDomain=true&key=[ourKey]', 
true);
xhr.onload = function () {
    var response = JSON.parse(xhr.responseText);
    //do something with the response
};
xhr.send();

Errors: SEC7120: Origin http://[ourUrl] not found in Access-Control-Allow-Origin header. File: ClientApiWrapper.aspx

GET /maps/api/place/queryautocomplete/json?input={55%20saddl}&types=address&language=en&crossDomain=true&key=[ourKey] HTTP/1.1
Accept: / 
Referer: http://[ourURL]/[ourOrg]/form/ClientApiWrapper.aspx?ver=1166920881
Accept-Language: en-CA
Origin: http://[ourURL]
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: maps.googleapis.com
Connection: Keep-Alive
Cache-Control: no-cache

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Date: Wed, 25 Apr 2018 16:26:36 GMT
Expires: Wed, 25 Apr 2018 16:31:36 GMT
Cache-Control: public, max-age=300
Server: scaffolding on HTTPServer2
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN

OK, so the browser is sending the Origin header. That means that your server needs to return some CORS response headers.

So you need to add code at the server to return the following CORS response header for OPTIONS, GET and POST requests:

Access-Control-Allow-Origin: <value of Origin request header>

(what I mean by that is that the server should extract the value of the Origin request header (i.e. http://[ourURL]) and return that as the value of the Access-Control-Allow-Origin response header. Don't hardcode it as 'http://[ourURL]' - that way lies madness!).

You will also need to return the following additional CORS headers for OPTIONS requests only:

Access-Control-Allow-Methods: <value-of-Access-Control-Request-Method request header>
Access-Control-Allow-Headers: <value-of-Access-Control-Request-Headers request header>
Access-Control-Max-Age: 86400

That last one specifies the number of seconds that the browser should cache the preflight OPTIONS response, so it doesn't need to get made each time. It is optional, but advised. 86400 seconds = 1 day.

That should get you going.

answered on Stack Overflow Apr 24, 2018 by roryhewitt • edited Apr 25, 2018 by roryhewitt
0

So, after all that messing around, I posted an issue on Google API dev support. Here's what came back...hope it helps other's trying something similar:

Thank you for posting. I can see that you are using Places API Web Service in your HTTP request. Places API web service is not intended to be used on client-side applications as responses don’t contain the Access-Control-Allow-Origin header. See more in the duplicate issue. To use Places API in a JS application, I suggest you use the Places Library in Maps Javascript API 1. This library offers an autocomplete2 feature that you can find in Places API web service. If you want the queryautocomplete feature of the web service, Javascript API provides getQueryPredictions() function as stated in the documentation 3.

answered on Stack Overflow Apr 26, 2018 by Lindsay

User contributions licensed under CC BY-SA 3.0