I am developing a service with an associated REST API for customers (companies which have their own websites) to use. In other words, one of my customers would typically make the REST call directly from their website (i.e. the request would originate from one of their customer's browsers).

I can of course provide an access token to give my customer access, but by definition it will have to be published publicly on their site, which means that anyone would have access to it.

The situation seems analogous to the use of Google Maps API keys, for example. Unless I'm mistaken, if I embed a map on my page, my API key needs to be public. As far as I know, the only protections against other people using my key are that I can restrict requests (with Google) to certain domains.

Is this the only thing I can do to restrict access to my customers? Is it possible for a non-customer to spoof their referring domain? If so, do people do this to use other Google API keys?

  • 4
    as a provider, you need to rate-limit or otherwise restrict access, in order to entice the site operator to proxy your API behind an on-domain server, to keep their key secret. You can't spoof a referring domain on unmodified equipment. – dandavis Oct 15 '18 at 17:42

The Referer field is easily spoofable, as it's a client-side variable. Don't rely on it for anything serious, like access control.

To control the domains allowed to use your API, you must ask them to proxy every access to your service, and use authentication on your side. This way when their customers access their site, the request will pass through their servers, a script there add the authentication details, and send to your server.

The client will never see the credentials, and you can ban or throttle the keys you suspect are misusing the service.

| improve this answer | |
  • I should have mentioned that possibility in my original question - I thought of that and that would be an obvious solution. However, is that common? It would obviously be much simpler to not involve an additional hop through their servers (though I can see how that would give them additional control, which is desirable). Second question - this is not how my Google Maps (for example) works (i.e. my API key is embedded in my site, for all to see). Does this mean that we shouldn't be following Google's example? Or am I completely missing something? – Jer Oct 15 '18 at 19:08
  • 1
    1 - This is almost the norm. A public API is public and anyone can access, a restricted one (your case) needs authorization, so you keep the keys on the server and proxy it to the clients. 2 - Google will check the originating domain, and will reject if there's a mismatch. It can be faked, sure, but Google is powerful enough to feed some freeloaders without any trouble, but you cannot. – ThoriumBR Oct 15 '18 at 19:45
  • what browser allows Referer to be altered? – dandavis Oct 15 '18 at 20:16
  • @dandavis Any browser allowing extensions. Or any user with a script on the backend proxying the API through its own server, or using curl to scrape data. There's lots of way to abuse an open API that only checks the Referer. – ThoriumBR Oct 15 '18 at 20:24

Modern browsers always send the Origin header on cross-origin requests (that include credentials), but older browsers may not do so. You can check that any requests originating from a modern browser only come from approved customer websites by checking the Origin header.

// Copyright 2018 Google LLC.
// SPDX-License-Identifier: Apache-2.0

The check origin header algorithm is as follows:

  • If there is no Origin header, or an Origin header is present with a blank value1, no conclusion can be drawn. Return "allow" from the check origin header algorithm.
  • If the Origin header is present, and it is not exactly one of your customer websites (in the form https://www.contoso.com), or a subdomain of one of your customer websites, then the request is from a genuine browser on a non-customer site. Return "deny" from the check origin header algorithm.
  • If the Origin header is present, and it is exactly one of your customer websites or their subdomains, the request could be from a browser or it could be from some other tool. Return "allow" from the check origin header algorithm.

Footnote 1: The text null, sent from data: and file: URLs, is not considered a blank value here. It is a mismatched value.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.