Is it safe to include an API key in a request's URL?

Summary: capability URLs are more secure than many people give them credit for, but not suitable for all applications, and require extra care to use.


These type of URLs are commonly known as capability / secret URLs.

It's meaningless to talk about security without specifying a threat model. Here are a couple that come to mind:

  • 1: A passive attacker on the network (eavesdroping)
  • 2: An active attacker on the network (can change packets at will, mitm, etc)
  • 3: A shoulder-surfer
  • 4: An attacker with physical access to your computer / elevated privileges
  • 5: another user of your computer (regular privileges / remote access)
  • 6: the user itself (as in protecting a API key)

Regarding network attacks (1 and 2), secret URLs are perfectly secure, provided you're using HTTPS (it's 2016, you shouldn't be using HTTP anymore!).

While the hostname of a server is sent in plaintext over the network, the actual URL is encrypted before being sent to the server - as it's part of the GET request, which only occurs after the TLS handshake.


Regarding shoulder-surfing (3), a secret URL with enough entropy is reasonably secure against a casual attack· As an example, I'll give a google docs URL:

https://docs.google.com/document/d/5BPuCpxGkVOxkjTG0QrS-JoaImEE-kNAi0Ma9DP1gy

Good luck remembering that while passing by a co-worker's screen!

Obviously, if your attacker has a camera and can take a picture without being noticed, it's an entirely different matter - you shouldn't use a secret URL in that situation. You can mitigate the attack by doing a HTTP redirect away from the secret URL, so it's only on screen for a few seconds


Regarding an attacker with elevated privileges on your computer (4), a secret URL is not less secure than a long password or even a client-side TLS certificate - as all of those are actually completely insecure, and there's not much you can do about that.

An attacker with regular privileges (5), on the other hand, should not be able to learn the secret URL as well, as long as you follow good security practices for your OS. Your files (particularly browser history) should not be readable by other users.


For protecting API keys (6, which was the point of this question), a secret URL is also no-less-secure than another mechanism (such as an AJAX POST). Anyone that has an use for an API key will know how to use the browser debug mode to get the key.

It's not reasonable to send someone a secret and expect them not to look at it!


Some people have asked about the risks on the server side.

It's not reasonable to treat server-side risks by threat modelling; from a user perspective, you really have to treat the server as a trusted third party, as if your adversary has internal network access on the server side, there's really nothing you can do (very much like a privileged attacker on the client's computer, i.e. threat model 4 above).

Instead of modelling attacks, I'll outline common risks of unintentional secret exposure.

The most common concern with using secret URLs on the server side is that both HTTP server and reverse proxies keep logs, and the URL is very often included.

Another possibility is that the secret URLs could be generated in a predictable way - either because of a flawed implementation, a insecure PRNG, or giving insufficient entropy when seeding it.

There are also many caveats that have to be taken into consideration when designing a site that uses secret URLs. This page by W3C TAG covers many of them.

In practice, for sites with dynamic content, it's quite hard to get everything done securely - both Google and Dropbox botched it in the past, as mentioned on this answer


Finally, secret URLs have a couple of advantages over other authentication methods:

  • They are extremely easy to use (just click the link, as opposed to entering your email and password)
  • They don't require the server / service to securely store sensitive user credentials
  • They are easily shareable without risks, unlike sharing you password (which you reuse for 50 other sites).

It depends on how that API is meant to be used and what type of data it is accessing. Something that accesses google maps (for example) is much lower risk than something accessing banking data.

Obviously a call like that in client side code is insecure, the user can easily learn your API key.

If the API call is made server to server, then it's less of an issue.

Using HTTP would leave the connection open to eavesdropping, HTTPS removes that problem.

Another problem with keys in the URL is the full url ends up in log files. That expands the attack surface for the app, as there are now more places to look for the key.

To answer your question, It's not that passing keys in the URL is inherently insecure, rather it's less secure than alternatives and not best practice. Assuming the API isn't accessing something sensitive, the connection is over HTTPS and the call is made server to server, it should be 'good enough' for low risk services.


It is not a good idea to pass secrets as GET parameters in general. I compiled a list on my blog a while ago on the potential security issues:

Secrets may leak to other parties as the following:

From your computer / smartphone

  • Your browser history
  • Cache files created by your browser
  • Shoulder surfing

Server-side

  • Web server logs
  • Log aggregating services such as SIEM, Elasticsearch, Splunk
  • Log files indexed by search engines (relevant Google dork)
  • Reverse proxy logs

To Third-parties

  • Proxy logs (e.g. in an enterprise environment)
  • Exception reporting services such as Rollbar or Sentry
  • Other websites via the Referer header
  • A friend, in case the URL is shared in an email or IM message
  • Fellow tenants in a public cloud

Some of them is not applicable to Ajax requests, but ymmv

Tags:

Http

Url

Tls