Security Tip: How Should APIs Respond to HTTP?

[Tip #123] If an API client tries to connect via unencrypted HTTP, what should your API do: redirect to HTTPS, disable HTTP, offer a swift rebuke, or take matters into it's own hands?

Security Tip: How Should APIs Respond to HTTP?

Last year I stumbled upon an interesting Tweet about API Tokens and HTTP connections. Check it out:

"Actually, API endpoints should listen for http and immediately revoke any tokens submitted."

The tweet links to https://jviide.iki.fi/http-redirects, which is a good read, but to save you the time, here's a quick summary:

Your API shouldn't automatically redirect from an HTTP (unencrypted) connection to an HTTPS (encrypted) connection, but instead HTTP should either be disabled or a clear error message returned that instructs the developer to use HTTPS instead.

This is to prevent API tokens (and other sensitive data) being sent over an unencrypted HTTP request in plain-text, where it could be easily intercepted via a Person-in-the-Middle attack (PitM/MitM), or logged anywhere along the request path by a third party and accessed/stolen later.

They include the example of a simple typo of http://api... during development of third-party API integration. The API redirected to https://api... automatically, so if this wasn't caught in dev review, their API tokens would have potentially been broadcast in plaintext for years.

While Graham, the author of the tweet, adds:

Actually, API endpoints should listen for http and immediately revoke any tokens submitted.

Which, if you think about it, makes a lot of sense:

As an API provider, if one of your users makes an API request over an unencrypted HTTP connection to your API, it doesn't matter if you reject the HTTP connection or return a strongly-worded rebuke in JSON or XML format, by the time they realise their mistake their API token has already been sent in plaintext over the internet!

It may already be sitting in an unprotected request log on a third-party's server, intercepted by someone with too much access on the network the device is on, or sitting in a three-letter agency's data-warehouse. If this happened in any other scenario, their API token would be considered stolen and should be revoked immediately. Graham is just suggesting that you, as the API provider, should do it automatically as soon as they make that unencrypted HTTP request.

Now, it's easy to say "revoke tokens on unencrypted HTTP connections", but it does mean a bit more infrastructure work is required, plus user notifications when tokens are revoked, etc.

Even just disabling HTTP for your API could be difficult if your platform enforces HTTPS redirects. It should be possible on Forge, since you can directly modify your Nginx config, but I believe Cloud will force the HTTPS redirect on you.

Also, don't think HTTP Strict Transport Security (HSTS) or the Preload list will save you either - that is enforced at the browser level. I believe command like tools like curl don't honour HSTS by default, and don't include the Preload list.

My Recommendations:

As with most security layers, you need to be pragmatic about this.

If you're working on a small app with a minor API, stick with whatever your hosting platform supports. If you can disable HTTP or return a strongly-worded rebuke helpful error for your API, then go for it, otherwise just leave the HTTP to HTTPS redirect and spend your time on other aspects of securing your app.

If you've got a popular app and heavily used API, you really should consider implementing one of the suggestions. Ideally revoking keys, but even just disabling HTTP or rebuking typos would be better than nothing.

⚠️
UPDATE: So it turns out I missed something rather important here. The article says "A great solution for failing fast would be to disable the API server's HTTP interface altogether and not even answer to connections attempts to port 80."

If disabling HTTP entirely for your API is something you can do, then this would be a good solution - API tokens will never be sent unencrypted, so you don't need to revoke them. This is something Cloudflare does.

However, this relies on your API being separate from your main application, so you can disable port 80 on the API while leaving it open for the required HTTP->HTTPS redirect on the main app, which is added complexity your infrastructure will need to handle.

Big thanks to @faker@infosec.exchange and Julius Kiekbusch for pointing this out! 👍

To finish up, I saw a fun reply to this tweet that I wanted to share. Note that I haven't been able to confirm if it's true or not, but the idea is brilliant!

"when discord sends signed webhook requests to bots, it will occasionally send and incorrect signatures, and disable your API key if you respond. more things should be like this!"

Let me know if you've come across any security features like this before, or would consider implementing something like this in your own app!


If you found this security tip useful? 👍
Subscribe now to get weekly Security Tips straight to your inbox, filled with practical, actionable advice to help you build safer apps.

Want to learn more? 🤓
Upgrade to a Premium Subscription for exclusive monthly In Depth articles, or support my work with a one-off tip! Your support directly funds my security work in the Laravel community. 🥰

Need a second set of eyes on your code?
Book in a
Laravel Security Audit and Penetration Test today! I also offer budget-friendly Security Reviews too.

Finally, connect with me on Bluesky, or other socials, and check out Practical Laravel Security, my interactive course designed to boost your Laravel security skills.