There exist numerous security concerns that deserve to be discussed when developing a RESTful API, due to their progressive diffusion and crescent adoption in modern web programming. Given the fact that the entire base of such technology relies within the (formally) stateless and completely insecure HTTP, much needs to be done in order to obtain reliable security policies for our data. This article aims to explore various effective approaches to implement these solutions.
Developing applications that need to support different clients the use of restful APIs has increased drastically becoming almost the standard.
One of the main problems of restful services, though, is the fact they are based on the http protocol that is insecure by definition.
Even if, to overcome this lack of security, http has been secured via SSL (also known as HTTPS) to protect the data in transition this often does not offer enough protection.
I will not discuss HTTPS during this post as I assume that any APIs should always use https regardless the requirements and the level of security implemented.
In many cases, when our project needs to deal with sensitive data, the security may become a very big problem and requires a big effort in terms of development and testing.
In my last 3 projects I had to develop applications where the security was a fundamental requirement.
In this post I would like to illustrate how I have met high security requirements using the following technologies :
Java Jersey (Jax-RS) + Eclipselink (JPA) (back-end).
For the nature of the post I will spend more attention on the back-end part (as usually is the part where the highest level of security is required), but I also want to explain how Angularjs is perfectly married to java jersey jax-rs (and not only) and its framework to secure Restful APIs. To do so I have decided to divide the post in two parts as follows:
Jersey is an open source, production quality framework for developing RESTful Web Services in Java that provides support for JAX-RS APIs and serves as a JAX-RS (JSR 311 & JSR 339) Reference Implementation.
Its main goal is to offer a set of tools to easily organize, protect and develop RESTful API using java and (in my modest opinion) is one of the best frameworks I used in the last few years to create restful APIs.
To learn more about it go to jersey project website
Security is something that needs to protect all the resources of the application and needs to control every request made to the server.
This process may be (and generally is) heavy and could slow down the application if not planned carefully.
Jersey offers the possibility to create filters and their biggest characteristic is that they are executed every time the server receives a request.
Using a particular notation (@Prematch, @Postmatch) we can decide when the server will need to execute the filter.
The terms prematch and postmatch refer to the fact that when the server receives a request, there is a phase before matching one of its resources with the one requested by the client and one after (post) the matching happened.
Knowing this appears logic to put our security in a filter in Prematch phase. If a request is insecure or not authorised we will not be bother to look for the resource and satisfy it but will reject the request immediately.
The main advantage of this is the increased security of the operation (the request will not even touch the resource is looking for if does not pass the check), and better performances (we just execute business logic for and only for legitimate requests).
Also all the logic regarding the security will be in one place, easily maintainable and testable instead of having it spread all around the application.
Thanks to the filter we can detect what the client is asking for (even if the match phase is not started yet) and we can run our security checks.
If, for example, we detect the client is asking to login we could leave the match phase to happen and generate a valid token after the credentials passed by the client are verified. This token will be bound to the user, stored somewhere and passed back to the client with the response. For all other requests the client will insert the token in the header and the filter will check it in prematch phase before serving the client.
It is good to apply some additional security to the token such as a time to live that will make the token invalid, forcing the user to go back to the login process once again, when the token expires and/or adding logic to protect the system from brute forcing attacks. The login function, for obvious reasons, is the most unprotected one and, to work around this, there are various ways that can be very specific from case to case.
Regarding the problem where to store the token there are many approaches: one could be saving it in the database another one in a hash map.
Both techniques are fine and have strong and weakness points so the decision on what system to use is driven by the requirements more than other factors.
Saving the token in a hash map is good because the server has to access this information often (every request) and having the token already in memory it is a very good advantage. The main problem is that if the application have many users this information (that often is also associated to users permissions) may use a considerable amount of memory. Also this solution makes the life hard on a clustering scenario.
On the other hand storing the token in the database it is better in terms of memory usage but worst in terms of performances.
Personally I find that a good compromise is to use memory tables in the database. These tables are loaded in memory of the database server and they offer a faster access than the "classic" tables. Most of the time they do not support relations between tables (foreign keys) and transactions but in this case these limitations are completely acceptable.
If it is possible taking advantage of the caching system of an ORM like eclipselink (and it is not always the case) even saving the tokens in the database may not be translated in a big lost in terms of performances. In this case the ORM may offers techniques to accommodate scenarios where the clustering is involved. For more details regarding this important aspect refers to this link
On my next Post I will illustrate the second part with a deeper look at EclipseLink.