Beyond the browser: Building secure APIs

Jacob Baskin
Coord
Published in
5 min readApr 25, 2018

Securing APIs isn’t like securing apps — here are the techniques we used to keep our customers safe.

“Is my service secure?”

The only answer to this question is another question: “secure against what?”

To make a system secure, you have to know the threats you’re trying to defend against.

Just as locking the door of your office won’t protect your site against exploits, even perfect web security won’t protect your company against issues like social engineering and rogue employees. Similarly, APIs, websites, and mobile apps all have different threat models. For websites, you have to worry about attackers running malicious code in a user’s browser. For mobile apps, you might worry about malicious apps on a rooted phone, or an attacker stealing a user’s device. So, what security threats do we worry about for APIs? And how do these differ from the security threats to applications?

In physical security, parking lot gate arms have a very specific threat model. They protect the parking lot owner, but not your belongings.

The Threat Model for APIs

In our model of an API, there are three different parties involved. There’s the API owner, who makes the API available; the caller, who builds the app that calls the API; and the user, who uses the caller’s app — and thus, indirectly, the API. We want to protect all three of these stakeholders from different things:

  • We need to protect the API owner from theft of services, where attackers can call an API without the owner being able to properly attribute their usage.
  • We need to protect the caller from theft of caller data, where attackers use the API to run reports or get aggregate statistics about the caller’s application.
  • We need to protect the user from theft of user data, where attackers use the API to get their personal information or steal their account credentials.

We assume that attackers can:

  • View the complete source code of our entire system;
  • View and run any website or application that we or any of our customers has made available to the public;
  • Get users to run their own malicious code — -but not within our customers’ applications.

On the other hand, we don’t assume that attackers can break browser or mobile OS sandboxing, nor can they decrypt TLS-encrypted requests.

Are API Keys Secure?

Almost every API you can think of makes you use an API key in order to call it. We certainly do! But do API keys help keep a service secure?

Different APIs use API keys for different purposes. Some companies, like Stripe, give customers an API key that will only ever live on their server. These API keys are secret, because an attacker would have to hack their callers’ systems to get them. Because of this, they protect both the owner and the caller: since you can’t pretend to be an existing caller without this secret, their data is safe. We call API keys like these client secrets.

It’s important to note that client secrets only work if your API is called from backend servers. The minute an API key goes into a publicly-accessible application, an attacker can find it and use it! At Coord, we want our API keys to be usable directly from websites or mobile apps, so our API keys aren’t secret.

In that case, why do we use them? Because they still protect the API owner. API keys let the owner track a given caller’s usage patterns, and even restrict them to a certain referrer or mobile application. If someone tries to use our API with one of our caller’s keys, we’d see right away that the usage doesn’t belong to the caller’s app. If we didn’t rely on API keys for this, we’d be unable to give our callers the ability to use our APIs directly from a website or app without a logged-in user.

We think the trade-off is worth it — -but this means that we have to assume anything that comes from a request that only requires an API key are fully public. We need a second method of authentication for any request that reveals sensitive data.

Safeguarding Caller and User Data

If we can’t rely on API keys alone, we need another way to protect caller and user data. For this, we use user tokens. A user token is a hard-to-forge, user-specific identifier that grants access to a particular user’s data for a limited amount of time. So even if an attacker got hold of a single user’s token, they would only be able to get the data for that user. If we implement user tokens right, they will be sufficient to keep user data safe from attackers.

To protect our callers, we issue the very same kind of tokens, but we give them to servers instead of to users. Many APIs call these “service accounts”, because the API owner treats their server the same way as they would treat a real user account. Unlike client secrets, callers generate service account tokens as needed, and these tokens are only usable for a limited time. The underlying secret information never leaves their control. These protections make it harder for attackers to steal service account tokens and limit the damage if an attacker does get hold of one.

Obviously, if the attacker could create their own tokens, our security would be compromised. This means that user tokens must be hard to forge. To make sure of this, we use JWT, an existing web standard for security tokens that lets us cryptographically ensure that tokens are valid and come from a caller that we trust. We’ll talk more about how we use and generate JWTs in a future blog post.

For user tokens to be secure, we also have to trust our callers to be good stewards of their users’ data. This is extremely important, but it’s out of scope based on our threat model, which means we have to ensure it through other mechanisms. As you can see, it’s crucial to understand what your security does and does not protect you from.

What’s Next

Secure APIs must be easy to call securely, and hard for time-pressed coders to misuse.

Any system is only as secure as its weakest link. We not only need to make our APIs secure, we need to make it easy to use securely, which is one reason why we decided not to rely on client secrets as a security measure. As we work with our callers, we keep learning more about how to make our APIs more secure and more usable at the same time.

In a few weeks, we hope to share some more detail of our authentication model to complete our discussion of user management in APIs. In the meantime, we encourage you to play around with our system: we’d love to hear about your experiences using our API keys, user tokens, and documentation.

--

--

Jacob Baskin
Coord
Editor for

CTO at Coord, bringing mobility online and connecting software to the physical world.