We already showed you how to build a Beautiful REST+JSON API, but how do you secure your API? At Stormpath we spent 18 months researching best practices, implementing them in the Stormpath API, and figuring out what works. Here’s our playbook on how to secure a REST API.
Industry standard authentication protocols help reduce the effort of securing your API. Custom security protocols can be used, but only under very specific circumstances. Here is a brief overview of the benefits and drawbacks of the top protocols.
Basic authentication is the easiest of the three to implement, because the majority of the time, it can be implemented without additional libraries. Everything needed to implement basic authentication is usually included in your standard framework or language library. The problem with basic authentication is that it is, well “basic”, and it offers the lowest security options of the common protocols. There are no advanced options for using this protocol, so you are just sending a username and password that is Base64 encoded. Basic authentication should never be used without TLS (formerly known as SSL) encryption because the username and password combination can be easily decoded otherwise.
Oauth 1.0a is the most secure of the three common protocols. Oauth1 is a widely-used, tested, secure, signature-based protocol. The protocol uses a cryptographic signature, (usually HMAC-SHA1) value that combines the token secret, nonce, and other request based information. The great advantage of OAuth 1 is you never directly pass the token secret across the wire, which completely eliminates the possibility of anyone seeing a password in transit. This is the only of the three protocols that can be safely used without SSL (although you should still use SSL if the data transferred is sensitive). However, this level of security comes with a price: generating and validating signatures can be a complex process. You have to use specific hashing algorithms with a strict set of steps. However, this complexity isn’t often an issue anymore as every major programming language has a library to handle this for you.
Oauth2 sounds like an evolution of Oauth1, but in reality it is a completely different take on authentication that attempts to reduce complexity. Oauth2’s current specification removes signatures, so you no longer need to use cryptographic algorithms to create, generate, and validate signatures. All the encryption is now handled by TLS, which is required. There are not as many Oauth2 libraries as there are Oauth1a libraries, so integrating this protocol into your API may be more challenging. Last year, the lead author and editor of the Oauth2 standard resigned, with this informative post.. Because of this instability in the spec committee and because OAuth2’s default settings are less secure than OAuth1 (no digital signature means you can’t verify if contents have been tampered with before or after transit), we recommend OAuth1 over OAuth2 for sensitive data applications. OAuth2 could make sense for less sensitive environments, like some social networks.
Custom authentication protocols should be avoided unless you really, really know what you are doing and fully understand all the intricacies of cryptographic digital signatures. Most organizations don’t have this expertise, so we recommend OAuth1.0a as a solid alternative.
Even if you are willing to take this potentially perilous road, there is another reason to avoid it: because it is custom, no one other than you will be able to use it easily. Only use custom authentication protocols if you are willing to support client libraries you can give to your REST API callers (Java, Ruby, PHP, Python, etc) so your users can use these protocols with little or no effort. Otherwise the API will be ignored.
What did we choose? At Stormpath, we do use a custom authentication protocol. It is very similar to OAuth1, but with many enhancements (for example, unlike OAuth1, Stormpath’s scheme uses the request body when computing the signature to ensure the body cannot be tampered with, among other things like additional key derivation functions). But again, this algorithm is useful only to clients that are using our SDKs that implement this algorithm. We also support other common protocols for clients that can’t use our SDKs.
One other technique we use is generated API Keys instead of traditional username/password. That decision is well-documented on our blog, but it’s also very important for API security, so here’s the Cliff Notes on API Keys:
API keys/secrets are usually a long series of random characters that are difficult to guess. Username/password are typically much smaller in length, use common words, are generally insecure, and can be subject to brute force and dictionary attacks.
Passwords are reset often. If you use the password as part of your API authentication scheme, API access would fail every time the password is changed.
Best practices say to encrypt your passwords in the database to limit a potential data breach. This increases overhead for each request when authenticating a user. Unique API keys authentication skips the hashing step and therefore speeds up your calls. If you want to know more about storing passwords, read more here.
At Stormpath we encourage storing the API key/secret in a file only readable by the owner. When the key/secret pair is downloaded, it is saved to the local file system. Then permissions are changed so that only the user can read the file. This limits the exposure of the key while keeping the key available for use with our SDKs.
In order to reduce security liability of your ids, you should make them opaque and globally unique. Instead of using “1234” use “f6cd3459f9a39c9784b3e328f05be0f7.” Not using sequential numbers helps stop attackers “guessing” the next number (known as a fusking attack), and prevents contention issues by being able to disperse UUID generation to any server, instead of waiting for a single database server to auto increment an ID. At Stormpath, we use what we call “Url62” for UUID generation. This is basically a globally unique generated byte array encoded using 62 ‘url-safe’ characters. This allows IDs to be safely used in URLs without having to worry about encoding problems.
Avoiding sessions for our REST API has been a good practice for Stormpath and helps improve our API server performance. In addition to avoiding the overhead of a session cluster (Database, Memcache, etc...), you can just add additional machines to your API cluster in order to grow with your user base.
When you are implementing an authorization scheme (i.e. rules for ‘who can see what’), try not to protect data or functionality based on a URL. URLs can change over time, so instead use the resource itself or its content as what you inspect to make your access control decisions.
Les, the CTO at Stormpath, also has a great video on REST Security.
Other/better ideas on API Security? We would love to hear them in the comments?