78

Currently Google requires you to create an API Key that is specific to the domain of where the map will be served from. How does Google enforce this? I want to do the same thing.

I expose an API for my service but want to allow clients to embed calls to the API via javascript and not just from the server. I could secure it with just a random token but of course this could be easily spoofed by anyone looking at the code on the client machine.

I always understood this concept to not be possible but somehow Google does a good job at enforcing it.

Edit - It sounds like Google really hasn't done anything amazing after all. Their API is most likely just for tracking and not really to guarantee that their API is used by the person with the key.

hippietrail
  • 15,848
  • 18
  • 99
  • 158
Vyrotek
  • 5,356
  • 5
  • 45
  • 70

5 Answers5

67

The API key itself is most probably a one way hash of the domain the key is associated with and a secret only the Google API server knows about. It may contain some other pieces of well-known (to Google of course) information. When you make a request from that domain, the API server takes the domain the request comes from and makes that same one way hash calculation and compares the two values.

For Ajax calls, they most probably use the referrer to get the domain of the document host. While the referrer can be spoofed, ultimately in order to use the API, you need to get Google javascript to execute in the document. At this point, this javascript can verify that indeed the document that invoked the Ajax API call originated from the target server. This is also spoofable of course, provided you have your own DOM implementation or on the fly modification of the script. However, this spoofing needs to happen on the client side and the chances that the website that wants to use Google API will be able to spoof the client software are quite small.

Note that since the API is essentially free, they could've offered anonymous access to their API as well. Apparently Google's intent is not to protect unauthorized access to it, but to ensure that they can gather as much data as possible about that data usage and be able to associate that usage with other data they've collected about the target domain. As such, I wouldn't expect the API key verification to be much more complex than what I described above - the ROI on more advanced approach is too low.

And of course there's also the concern of possible XSS attacks through their API. But I don't believe their API key is tied too much into any anti-XSS code they have.

Franci Penov
  • 74,861
  • 18
  • 132
  • 169
  • Unfortunately this sounds like the most reasonable answer. Thanks for your input. – Vyrotek Feb 13 '10 at 06:01
  • 2
    "they could've offered anonymous access" - Note that some functions are limited by number of requests per day and API key (and have been when this was posted), e.g. reverse geolocation. – Piskvor left the building Oct 21 '11 at 09:57
  • 1
    Also note that usage on HTTPS is not free. – Arjan Sep 08 '12 at 12:28
  • Franci could you further explain in the second paragraph how the javascript can verify that the javascript that invoked the Ajax API call originated from the target server? – Govind Rai Mar 03 '18 at 19:44
31

I'm quite certain they use the REFERER URL to determine where the call is coming from. If the domain doesn't match what's assigned to the key, it's an invalid request.

For a practical example, using PHP you can check the domain using $_SERVER['HTTP_REFERER'] to check the referer. If the domain matches, return a valid response. If it doesn't, you can return a 401 Unauthorized or other response.

Trevor
  • 6,659
  • 5
  • 35
  • 68
  • So if a client were to make an AJAX call to our API via JavaScript I can depend on the Referer Domain to be accurate and non-spoofable? – Vyrotek Feb 13 '10 at 03:08
  • 4
    Nope. It is spoofable. I think Google more likely relies on the IP Address (can't be spoofed easily), and a DNS lookup. – Tyler Carter Feb 13 '10 at 03:10
  • Ah, so they take the domain URL and look up it's IP and lookup the DNS to make sure its a match. Although, you say this is technically spoofable as well? – Vyrotek Feb 13 '10 at 03:13
  • The referer sent in the request can be spoofed (http://en.wikipedia.org/wiki/Referrer_spoofing). – Trevor Feb 13 '10 at 03:14
  • It might be. Not 'completely' sure about its spoof-ability. But my guess is its more likely that Google us using the IP Address than using the REFERER. – Tyler Carter Feb 13 '10 at 03:14
  • 29
    The API address for an Ajax call is the IP address of the user agent of the client, that parses the document and executes the javascript. As such, the IP address of the Ajax request is unrelated to the document originating domain. The only information in the request that relates to the document domain is the referrer. Of course, the referrer can be spoofed. However, in the case of the Google API, it would be the website that wants to spoof the referrer; however, the actual spoofing can happen only on the client side in the browser. Thus, spoofing is not that big of a threat. – Franci Penov Feb 13 '10 at 04:37
  • 1
    The check is made by the GMaps Javascript code, **at the client side**. No need to check/spoof the referrer in this case... – Wim Feb 16 '10 at 19:37
  • 1
    @Wim - this is interesting. So to clarify, when you embed the GMaps javascript on your site, it is *custom* JS just for your site? That would mean Google returns a modified version of the JS for each website? Or do you think the js is doing 2 calls: one to figure out what site it should be on and one to send the data? – Brian Armstrong Apr 02 '10 at 06:54
  • 1
    @Brian: have a look at the main JS file you include for GMaps: http://maps.google.com/maps?file=api&v=2&key= Your key is somewhere in there, so you do get a (slightly) customized JS for your site (and I'm assuming that the key in some way contains an encoded value of the domain it's supposed to run on) – Wim Apr 02 '10 at 12:39
  • based on php documentation about $_SERVER['HTTP_REFERER'] is "The address of the page (if any) which referred the user agent to the current page. This is set by the user agent. Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. In short, it cannot really be trusted." so how we can depend on something that can be trusted ?. Thanks – Ahmad Oct 20 '11 at 14:16
  • 5
    many 'popular security solutions' strip or replace the referer by default. Do those users get blocked from seeing the service? – Instine Jan 20 '12 at 17:29
  • Up until a few months ago I thought I knew the answer to that. The fact that requests from _some_ browsers come in without a referrer doesn't actually matter. Google lets it through. Google can block invalid referrers, and that is enough to make it hopeless for a bad person to _build a website_ with a stolen API key. However... In a move I find surprising, as of this year, newer browsers are now supporting a meta tag, which allows people to make a website which instructs it to send no referrer header. http://stackoverflow.com/a/28836003/338265 So I guess that blows that idea – Harry Wood Aug 16 '16 at 00:36
  • 2
    An abuser can spoof the API key and use a modified referer to steal the quota of a company from his web browser. It is limited to the web browser (client). Do you think that google is limiting in some ways the number of requests an identified client (unique IP address) can make in a given time frame? That could limit the impact of the quota theft. – Nitseg Aug 21 '16 at 16:30
4

As my comment says:

The REFERER is spoofable, so it is probably unlikely that Google will use it as a means of verification. See this wikipedia entry.

My guess is that Google probably uses the IP address of the caller along with a DNS lookup. DNS is not really spoofable, as your DNS entries have to be correct for the website to even get to you.

But, even that has its problems, because if a server uses a Round-Robin IP Address DNS setup, Google will be redirected to a different IP address when doing a DNS lookup.

From the FAQ

Note that a key for http://www.mygooglemapssite.com/ will only be accepted when the site is accessed using this address. It will not be accepted if the site is accessed by IP address (eg. http://10.1.2.3/) or by a hostname that is aliased to www.mygooglemapssite.com using a DNS CNAME record.

My guess is that it might be using the Host header that is sent when requesting the page, which would work as normally Google asks you to include it's API script directly into the page. Then that script has access to the headers for the current page and can use that to check.

My guess is backed up with the fact that it does not work for IP addresses or Aliases, which means it isn't doing a DNS check.

THIS method cannot be spoofed, as it must be the correct header to access the page. However, this means that any aliases to the domain will not work.

However, this also means that you MUST provide a Javascript library to access the code, as you can't check this server side, I believe.

Tyler Carter
  • 60,743
  • 20
  • 130
  • 150
  • The 'Host' header may contain the address when requesting the page, but how would I guarantee that value is also passed into the new AJAX request made by that page to my API? I thought this is basically what 'Referrer' contains which we know can be spoofed. – Vyrotek Feb 13 '10 at 04:01
  • Well, because YOU are writing the AJAX call (because you provided the Javascript library), YOU can make sure it gets sent. – Tyler Carter Feb 13 '10 at 04:09
  • The Reason Google can require an API Key is because they provide the Javascript library, and can then run Javascript on the page. – Tyler Carter Feb 13 '10 at 04:10
  • 1
    Right, but anyone can see the code loaded onto the client and make modifications to send any domain url they want. So its still not secure. – Vyrotek Feb 13 '10 at 05:38
  • How is the IP address of the caller (being the web browser) related to the website that the browser is showing? Also, `Host` is set to a Google domain (to which the request is made), not to the domain of the site that includes the Google script (from which the request is made)? – Arjan Sep 08 '12 at 12:33
  • 6
    This answer is incorrect. As Arjan just said, the Host header for a call to a google API would be set to "google.com" so no use whatsoever. The IP address, is the IP address of the client (the computer where the web browser is running). Also no use. The only useful header coming from the browsers, is the referrer, which gives the website the browser is looking at. Do browsers always send this 100% reliably? No. Can a bad person break a single browser to send different referrer? Yes. Can a bad person make a website which instructs *all* the browsers to do this? No. So it works as tracking info. – Harry Wood Apr 22 '15 at 14:23
4

I agree with all the points that Franci Penov has listed. I would like to elaborate a little bit on using someone else's API key. Let us assume you register key1 with example.com.

  1. First attempt – If anothersite.com has <script src="http://www.google.com/jsapi?key=key1">, Google could check its referrer (hash scheme mentioned) and in this case there is a mismatch. How does evil attacker overcome this, since a lot of people have mentioned that referrer can be spoofed? This does not really apply here. Sure you could send arbitrary headers if you make the request, but how does evil hacker spoof referrer for users on anothersite.com? This is in general not easy. There have been old versions of flash on IE 6 that allowed attacker to set arbitrary headers when making cross domain requests, but in general this is not workable for script src. I am not sure if the included Javascript does any validation of document.location to prevent this (probably not).

  2. Second attempt – An evil attacker copies Google Javascript for the API key from mysite.com's page source and then embeds modified javascript on anothersite.com. Now Google can't check anything (the remote IP will be the user's computer, and there isn't a whole lot you or Google can do).

So, if you want to for some reason keep your API key secret (one reason, malicious person can get your key blacklisted/blocked), then don't embed key in client and proxy requests via your server (your application code now has the key).

Michael
  • 8,362
  • 6
  • 61
  • 88
mar
  • 356
  • 1
  • 6
-6

The reason it works is that you cannot make API calls with javascript. Browser security prevents javascript from making requests anywhere except to the domain that the javascript originated from. Because of this, any API calls from javascript need to be bounced through your server where the API key is stored (the api key is never seen by javascript).

Jeffrey Aylesworth
  • 8,242
  • 9
  • 40
  • 57
  • 2
    There are ways around this though (JSONP). I don't think its that you can't make the call, you just normally can't process the return. – Ryan Elkins Feb 13 '10 at 05:07
  • Looking at a few examples and especially http://econym.org.uk/gmap/example_map12.htm (listed as a good tutorial) it appears that typical user expose key when they script src maps api. The sourced js overwrites the page (map is a set of img). Markers are placed by downloading json data using GDownloadUrl() - this just makes a XMLHttpRequest and so is back to his server. JSONP requires support from google server, right? – mar Feb 16 '10 at 19:54
  • 4
    If this were true, then for example CDN hosted jQuery could not make Ajax calls to any other domain than the CDN. – Arjan Sep 08 '12 at 12:35