0

I'm developing an API service and I would like to allow the users to restrict access of their tokens by domain, so an API key can only be used from one site/domain/host (it could be a server calling the API, not necessarily a browser), like Google Maps API allows you to do.

Now my question is, how do I check which host/domain the request comes from - in PHP (Laravel) - so I can compare it to the allowed domain(s) or pattern?

Is $_SERVER['REMOTE_HOST'] the right variable to check? Or should I look at a request header? Like $_SERVER['HTTP_ORIGIN'] though that seems to be browser related and, if I'm not mistaken, another client (a server or Postman for instance) would not necessarily have the Origin header, while $_SERVER['HTTP_HOST'] is not required and can be faked.

Edit: just to be more specific, I don't think this additional check on the requesting domain is supposed to replace the access token for auth, but it is an additional layer of protection and helps with token management and misuse - a user might have multiple tokens for different clients/apps calling your API so this way you can discriminate the traffic. If Google can do it I assume there is a way for implementing it. Could it be not possible in PHP? I don't know, but I was hoping somebody here could suggest a way to implement this check/restriction, maybe underlying the limitations of the proposed solution. Even if the solution is not 100% reliable (again it is not suppose to authenticate the client) it would still help improving protection - in fact Google considers it best practice to "protect" the API keys this way.

Stefano
  • 555
  • 1
  • 5
  • 18
  • If the request isn't coming from a browser, but from server-side code, then you can probably just check the IP address - normally they're static for public servers. You're right, the Origin header is not compulsory and is also spoofable, you can't rely on that. – ADyson Oct 18 '22 at 23:53
  • Usually IPs are static, but not always. Anyway, even if not reliable (again this additional check is not supposed to replace the access token), what variable or header should I use? Again, if not available I can just kill the request, as long as I target a header that any legitimate client can - or normally should - set. – Stefano Oct 19 '22 at 00:01
  • 1
    REMOTE_ADDR gets you the IP of the requestor, as per https://www.php.net/manual/en/reserved.variables.server#refsect1-reserved.variables.server-indices . It's not a header set by the client, but a fundamental underlying property of the network communication on which the request was made. So it's not modifiable by the client. You'll get the public IP of the requestor, always (unless you have some setup in your network such as a reverse proxy in front of the webserver which forwards requests on...in which case you always get the IP of the proxy, unfortunately). – ADyson Oct 19 '22 at 00:03
  • So how does Google do in their API? – Stefano Oct 19 '22 at 03:19
  • @Stefano how google does their APIs is a way too broad question, isn't it? As others said, you can only restrict your API consumption to a list of IP addresses, but it has too many drawbacks. Much better to restrict access to access tokens. – Nemoden Oct 19 '22 at 04:34
  • @Nemoden I meant how does Google restrict the requests to specific domains? Which is exactly what originated my question. Now if they can do it I assume there is a way for others to do the same. I think that's an interesting topic. – Stefano Oct 19 '22 at 05:02
  • I edited my question, hopefully that gives a clearer scope of my question – Stefano Oct 19 '22 at 05:36
  • 1
    Doesn't the documentation you yourself linked to already tell you what Google does? _"IP addresses: Specify one IPv4 or IPv6 address or a subnet using CIDR notation. Since a web service request checks and compares the external IP address against the API key restriction, use the server's public IP address."_ - so they are simply checking the public IP address of the requesting server, exactly as you have already been told here ... – CBroe Oct 19 '22 at 06:21
  • @CBroe I am referring to the "HTTP referers" Restriction type – Stefano Oct 19 '22 at 06:57
  • 2
    Same as CORS, that pretty much only applies to browsers. The referrer is the URL of the page that an action (link click, API request) was started from - so that does not actually exist, when the request is made from the server side. Sure a referrer _could_ be sent with those request - but the value would be freely picked by whoever's in control of that server-side code. The referrer coming from the browser can also be manipulated - but that is much less likely, and for a majority of users, it will likely be a "genuine" one, so that the measure is still quite effective. – CBroe Oct 19 '22 at 07:11
  • Thanks @CBroe, so this measure is mostly useful if the API is meant to be consumed in the browser (like google maps in fact). Thanks that makes sense. – Stefano Oct 19 '22 at 07:22
  • Do I understand correctly though that `REMOTE_HOST ` would return the host name from a DNS lookup of the `REMOTE_ADDR` IP, or the IP if a lookup is unsuccessful? That would work for any client request, wouldn't it? – Stefano Oct 19 '22 at 07:28
  • 1
    As @ADyson said, that gets you the IP address (or host name, if exists), of the machine making the request. That could be a browser, or something on some web server. Important to be clear about the meaning of "client" here - when your web server makes a request to some other source, then your server _is_ effectively playing the client role in that HTTP transaction. – CBroe Oct 19 '22 at 07:32

0 Answers0