Securing GPXZ API keys in webapps

Most requests to the GPXZ API require an API key.

Typically, these keys are kept private inside an application and not exposed to end users. However, web-based and mobile applications run on end users’ devices, where it’s possible to extract the key.

If you need to make an API key public, we recommend at least creating an application-specific key with minimal scopes and domain restriction.

CORS header

By default, the GPXZ API sends responses with the header access-control-allow-origin: * . This means you can make requests from a browser-based application: such requests are sometimes called AJAX or XHR requests.

If you would like to rescrict the origins which can send requests using a certain API key, you use the “access-control-allow-origin” setting on that key. A valid origin looks like this: https://www.example.com, it needes a scheme/protocol and a hostname/domain.

Note that a CORS restriction isn’t enough to keep your API key secure. If you include your key in a public application, anyone can see your key and use it to make non-browser-based requests.

Allowed domains

You can further limit access by adding domain restrictions to an API key. This means that the key will only work for requests that originate from the domains specified.

Domain restriction works by checking the Origin and Referer headers, which most browsers send on every request. Requests that don’t match an allowed domain will be blocked with a 403 status code.

Each allowed “domain” is technically a hostname: a domain plus optional subdomains. Requests from subdomains of the proided hostname are allowed: so www.example.com will match requests from a.b.c.www.example.com as well as from www.example.com, but not from api.example.com or example.com. You may want to include localhost for local testing.

There are some situations where the Referer headers isn’t sent: for example, privacy-focused browsers don’t set this header. Because of this, requests without either of these the Refer or Origin header will be allowed, even if allowed domains are specified.

Note that, just like a CORS restriction, if you make your API key public then the allowed domains restriction will only prevent unauthorised requests originating from a browser.

Scopes

Scopes let you restrict the endpoints which an API key can be used for, limiting that key’s usefulness for an unauthorised user.

Any API key, even with no scopes added, is able to access endpoints which don’t requuire authentication. This covers GPXZ’s meta endpoints

  • /v1/elevation/sources
  • /v1/elevation/supported-raster-projections
  • /v1/health

Proxying

To fully prevent leaking your API key, the “proper” solution is to run a service which proxies requests to GPXZ, injecting your API key at the proxying level.

In nginx, that would look something like

server {
    listen 80;
    server_name gpxz-proxy.example.com;

    location / {
        proxy_pass https://api.gpxz.io;
        proxy_set_header x-api-key "YOUR_GPXZ_API_KEY";
    }
}

That way, you can perform your own access control and abuse mitigation, such as rate-limiting and request validation.

Help!

Reach out if you need any help or are seeing unauthorised access of your API key: [email protected].