Before you start reading, I owe you an apology for the clickbait. I’ve only prepared 8 checkpoints, but since this is 10 in octal, I’ve decided to make this hermetic joke. Nonetheless, here you are: things I consider important while designing your web application.
1. Think about what you need to secure your API against
OK, I can virtually hear the sarcastic “thank you captain obvious”. I will spare you any trouble and paste proper meme myself:
But now, jokes aside, let’s think about why it’s a problem. Let’s imagine that you have a service where users can create their own accounts. You implement decent password storing and, in case a user forgets the password, also a reminder that sets a one-time password that is mailed to the user. Sounds like a proper solution? What will happen if this email gets captured (because the person didn’t log out of their computer at university) or the user does not change the password? Your entire effort in providing proper password protection would get wasted. To make it worse, it would be broken by design. In order to fix this, you will have to rebuild your application.
In other words, try to identify protection measures that can be easily bypassed with a little creativity.
2. Do not reinvent the wheel
It might be tempting to come up with a new, outstanding API security measure. The problem is that the number of non-obvious issues can be surprising. Unless you really do know what you are doing, it’s better to stick up to standard solutions available. Thinking about token authentication? Use JWT from some standard library. Want to hash password? Read what your framework already provides and what do the smart people suggest. For example, look at what Spring or Django provide by default.
This lets you reduce the risk of implementing anything in a buggy way that would give you a false sense of security.
3. HTTPS in API security
HTTPS is a standard HTTP protocol that has been with us since the earliest days of the Internet, which has its communication encrypted with TLS. It means that you are safe when using HTTPS, right?
The important thing here is to understand what does TLS give us and what it does not:
- it allows us to send sensitive data through untrusted servers (which happens all the time, no matter whether it is an open hotspot in a hotel or our home, at some point all information goes through servers we can’t trust), by ensuring that our data can’t be read or modified,
- it confirms the identity of the host we are talking to - the certificate issued to example.com can only be used by example.com,
- it does not provide any protection against phishing, XSS or any other attack that takes place when the traffic is already decrypted.
4. Strong authentication for API security
What exactly does it mean “strong”? There are a few points to keep in mind:
- use proper cryptographic libraries for generating authentication tokens (again: do not reinvent the wheel);
- invalidate tokens on a regular basis - setting separate refresh and authentication token can help with this;
- test for failure: check if an unauthenticated user actually can’t log in, check if logging out actually invalidates tokens;
- avoid sending credentials in places from which they might leak, eg. in URLs. Request headers are a better place.
5. Proper authorization and assigning minimal required permissions
Once the user is authenticated, authorization (i. e. checking what resources they should be allowed to access) comes in. This is a hard design decision: creating roles for users which will allow them to do what they need while keeping sensitive areas closed, properly filtering resources they can access… Some frameworks (like Django - remember do not reinvent the wheel) have built-in authorization model which you can use in API security development, sometimes you will have to create your own (check our django-trench, an open-source library providing multi-factor authentication for Django). Things to consider while approaching these tasks are:
- allow only minimum required privileges - if your accountant does not need access to your employers’ emails - do not give it;
- if your accountant needs those emails to send information about salaries, but you can hide this information with the proper interface - do it;
- test whether your access limiting actually works. Can someone bypass some restrictions simply by asking for it?
6. Rate limiting
In order to secure yourself against DDoS or brute-force password guessing you might want to establish a limit on the number of requests a single user is allowed to make. I am pretty sure that making 1000 login attempts should seems suspicious. On the other hand, if you provide a service where many automated requests are made, you might want to loosen this limitation, but allow certain users only to make a certain amount of requests according to pay plan.
In modern web applications, an Origin is a basic unit within which sharing resources happens (hence Cross-Origin Resource Sharing). Generally, one origin can’t read another’s data (with some exempts). In order to loosen this policy, the CORS mechanism has been created. This allows 2 different origins (e.g. frontend application served from a different origin than backend API) to communicate with each other.
Web Application Firewall is your first line of defence because it is the first place request touches on your infrastructure. It works like a firewall on your computer, but it is designed to protect your application, not PC. It can be used to filter out malicious requests trying to exploit known vulnerabilities or using standard techniques like SQL injection. I guess it could be useful in this case, although the risk of false-positive is a different matter.
Here're some additional resources: