REST API security review - rest

I'm working with some people who have had a product in development for a while, with apps on various platforms calling a web service which they're using as an API to store data.
The security model they have developed is not completely unlike others i've worked with, but it's very non-standard in a lot of ways. First, they require an API key for each client, which makes sense. Then there are some methods you can hit without authentication, great. when you need to do authenticated updates, however, this is how they do it:
First you call an endpoint with a username/password to get a "session" going on the server side. this session id is returned to the client after a successful login. Everything else you do that requires authentication takes a session id parameter which is required and the idea is that if you don't supply a valid session id then reject your requests.
I spent some time a while back doing authentication using OAuth and requiring tokens for authenticated requests on another project, so this feels weak to me. One obvious issue is the potential for someone to hijack someone's session by means of a brute-force attack, but I expect they'll dismiss that as just plain unlikely. Their session Id's are GUID's, which I suppose are huge and difficult to hack on some scale, plus you have to hit a valid session that's already established.
Am I missing something obvious, or is this perhaps good enough? I don't want to raise a stink about it and propose a platform-wide migration to OAuth if I can't make the case that it's really necessary.
Thanks for any help.

This sounds acceptable, just make sure that GUIDs are indeed generated with a strong random engine that can't be brute-forced, and that they expire after a while of no activity.

First of all, requiring an API key is a form of authentication. It authenticates the client instead of the user.
Requiring an API key on all clients increases the risk of losing the key (especially when stored on untrusted clients like mobile devices).
Using session identifiers is not insecure, but it does require talking to the issuer (and likely doing a database lookup) for every call.
Security tokens can carry semantic information (claims) and can be validated on the called server (verifying signature), which improves scalability.

Related

What benefit does JWT provide?

I have implemented JWT based security in a test Core Web API REST project, it is working fine but I am not sure that I see the benefit of this. The web says JWT is good because it's lightweight and can be used to verify that the source of data but in my implementation:
The client first provides a username and password to authenticate
If user + pwd is ok the a token is returned and every subsequent call to the api uses that jwt token (instead of the username and password) to authenticate.
This is fine but why not just use the username + password on every call to the api (and skip the complication of managing the token)?
In fact in my case there's additional complications because I now have to factor in an expiry date (of the token) that resides outside of my system.
Can someone explain what I'm missing here?
One of the main benefits and motivations for using JWT is that it allows your server side application to push all session state information outside of the application. That is, in a theoretical limit, a JWT implementation is actually stateless.
To directly answer your question, we can compare the workflows for what happens when username/password is submitted in every request versus submitting a JWT.
First, a JWT contains a claims section, which is typically written by the issuer of the token, i.e. the server side application. One of the fields is called exp, and contains the expiry time of the token. One property of JWT is that it is not possible for the user to tamper with them. This is enforced via a checksum, which would change if any part of the JWT changes. Taken together, this means that the user cannot alter the expiry time (or any other claim), and the server can implicitly trust this time. When the user submits a request with a JWT, in theory all the server has to do is just check exp to see if the token still be valid. That is, the session state actually lives outside the application, at least in theory.
In contrast, when the user submits a username/password each time, the server has no way of knowing what to do just based on that information. Rather, the server has to maintain the session state itself, and this can be costly both in terms of memory and performance.
In practice, JWT is never completely stateless, but, using a good implementation, it is usually possible to get the memory footprint very small, requiring only a bit of space in a cache (e.g. Redis or a similar tool).

What's the benefit of JWT if user needs to send his credentials once anyway?

JWT tokens seem like a very good idea. You can send a request to some API without using your username/password secret pair.
Still, I don't fully understand the benefits that it gives. I have two questions:
To get the token, user still needs to send his credentials to some server that issues these tokens. Isn't it a weak point of all this?
If attacker steals the token while it's being transferred, he can use it to pretend he is someone else. The only difference between this and using user/password combination is that JWT tokens get expired after some period of time, so attacker doesn't have much time to do his thing.
Is my understanding correct? What am I missing?
Yes, it does have to exchange the pair once, but this is still minimised risk compared to doing it every time you have to make an API call.
There are many ways tokens can be stolen, and the common way to detect this is by checking for sudden unexpected changes in IP addresses. This method is not robust and is easily spoofed. However, if we're able to detect the theft, then it's a simple matter of blacklisting the token. Hence, the entire strategy is dependent on detecting that the theft has occurred. For this reason, you should use the concept of rotating tokens: See more in this blog for how this would work as it's too long to explain in a SO answer.

JWT logout feature without using blacklist?

I have used JWT before, but they were API that didn't need logout feature.
I need to implement logout feature for a API of an android app and SPA. When I looked it up I found that there are two ways to do it.
the easiest way is to delete the JWT Token from client side and call it a day.
The logic behind this is that since no session of any kind is maintained in server deleting the token in client side should be enough.
But it still leaves the possibility that, if the token falls in wrong hands they can still use it even after the user is no longer using the token.
Given if the app is well designed and uses HTTPS then chances of this happening is very low and can be minimized by keeping the valid time for the token short. But in my case the tokens are valid for 30 days.
the second option is to maintain a blacklist of tokens in server side
This solves the problem of the token still being usable even after user has logged out and stopped using it.
But it adds a complication of needing to run a cronjob to remove expired token form the blacklist table. Otherwise the table will eventually become ridiculously large.
It also kinda defeats the point of using JWT. Maintaining blacklist is very similar to maintaining session. We have to run an additional db query for every request. And it scales badly, as the no. of users grows the no. of token that needs to be blacklisted will also grow (this will be a bigger problem for API like mine with multiple front end apps and long validity period for the tokens).
Then I got an idea for third way.
Add jwt_secret row in user table that stores randomly generated string. Use it to sign the JWT Token then on every request use user id in the jwt payload to get the user form db(which is not an extra query, we have to do this anyway) and validate the token signature using jwt_secret of the user. When the user logs out we change the jwt_secret which makes all token out there useless.
At first I thought this was a great solution only to realize that in this setup if user logs out of one device or browser he/she gets logged out of all devices.
So is there a another option? Or a way to modify any of above approach to solve the problem. Or am I over thinking this and one of the above option should be used?
For logging out, which as you pointed out is a user initiated action, I don't think you need to do anything extra. If the user somehow did not delete his JWT, then so be it. He wouldn't be getting any extra access over to what he is already entitled.
However, your question seems to hint on the problem of how to know that a JWT is valid. Again, as you pointed out, if a JWT somehow fell into the wrong hands, then there may be no avoiding this. But, with each request you would typically be doing several types of validation against that JWT, e.g.
checking the claims of the JWT, such as the token expiry date
assuming the claims pass, then checking that user's ID against your database table to make sure the account is active, has not been suspended, etc.
My point here is that if you need to keep track on the server side that a logout has happened, you might need to persist this to a database. But, I don't think you would need this.

Can I use a session identifier in a REST API? [duplicate]

Is using sessions in a RESTful API really violating RESTfulness? I have seen many opinions going either direction, but I'm not convinced that sessions are RESTless. From my point of view:
authentication is not prohibited for RESTfulness (otherwise there'd be little use in RESTful services)
authentication is done by sending an authentication token in the request, usually the header
this authentication token needs to be obtained somehow and may be revoked, in which case it needs to be renewed
the authentication token needs to be validated by the server (otherwise it wouldn't be authentication)
So how do sessions violate this?
client-side, sessions are realized using cookies
cookies are simply an extra HTTP header
a session cookie can be obtained and revoked at any time
session cookies can have an infinite life time if need be
the session id (authentication token) is validated server-side
As such, to the client, a session cookie is exactly the same as any other HTTP header based authentication mechanism, except that it uses the Cookie header instead of the Authorization or some other proprietary header. If there was no session attached to the cookie value server-side, why would that make a difference? The server side implementation does not need to concern the client as long as the server behaves RESTful. As such, cookies by themselves should not make an API RESTless, and sessions are simply cookies to the client.
Are my assumptions wrong? What makes session cookies RESTless?
First of all, REST is not a religion and should not be approached as such. While there are advantages to RESTful services, you should only follow the tenets of REST as far as they make sense for your application.
That said, authentication and client side state do not violate REST principles. While REST requires that state transitions be stateless, this is referring to the server itself. At the heart, all of REST is about documents. The idea behind statelessness is that the SERVER is stateless, not the clients. Any client issuing an identical request (same headers, cookies, URI, etc) should be taken to the same place in the application. If the website stored the current location of the user and managed navigation by updating this server side navigation variable, then REST would be violated. Another client with identical request information would be taken to a different location depending on the server-side state.
Google's web services are a fantastic example of a RESTful system. They require an authentication header with the user's authentication key to be passed upon every request. This does violate REST principles slightly, because the server is tracking the state of the authentication key. The state of this key must be maintained and it has some sort of expiration date/time after which it no longer grants access. However, as I mentioned at the top of my post, sacrifices must be made to allow an application to actually work. That said, authentication tokens must be stored in a way that allows all possible clients to continue granting access during their valid times. If one server is managing the state of the authentication key to the point that another load balanced server cannot take over fulfilling requests based on that key, you have started to really violate the principles of REST. Google's services ensure that, at any time, you can take an authentication token you were using on your phone against load balance server A and hit load balance server B from your desktop and still have access to the system and be directed to the same resources if the requests were identical.
What it all boils down to is that you need to make sure your authentication tokens are validated against a backing store of some sort (database, cache, whatever) to ensure that you preserve as many of the REST properties as possible.
I hope all of that made sense. You should also check out the Constraints section of the wikipedia article on Representational State Transfer if you haven't already. It is particularly enlightening with regard to what the tenets of REST are actually arguing for and why.
First, let's define some terms:
RESTful:
One can characterise applications conforming to the REST constraints
described in this section as "RESTful".[15] If a service violates any
of the required constraints, it cannot be considered RESTful.
according to wikipedia.
stateless constraint:
We next add a constraint to the client-server interaction:
communication must be stateless in nature, as in the
client-stateless-server (CSS) style of Section 3.4.3 (Figure 5-3),
such that each request from client to server must contain all of the
information necessary to understand the request, and cannot take
advantage of any stored context on the server. Session state is
therefore kept entirely on the client.
according to the Fielding dissertation.
So server side sessions violate the stateless constraint of REST, and so RESTfulness either.
As such, to the client, a session cookie is exactly the same as any
other HTTP header based authentication mechanism, except that it uses
the Cookie header instead of the Authorization or some other
proprietary header.
By session cookies you store the client state on the server and so your request has a context. Let's try to add a load balancer and another service instance to your system. In this case you have to share the sessions between the service instances. It is hard to maintain and extend such a system, so it scales badly...
In my opinion there is nothing wrong with cookies. The cookie technology is a client side storing mechanism in where the stored data is attached automatically to cookie headers by every request. I don't know of a REST constraint which has problem with that kind of technology. So there is no problem with the technology itself, the problem is with its usage. Fielding wrote a sub-section about why he thinks HTTP cookies are bad.
From my point of view:
authentication is not prohibited for RESTfulness (otherwise there'd be little use in RESTful services)
authentication is done by sending an authentication token in the request, usually the header
this authentication token needs to be obtained somehow and may be revoked, in which case it needs to be renewed
the authentication token needs to be validated by the server (otherwise it wouldn't be authentication)
Your point of view was pretty solid. The only problem was with the concept of creating authentication token on the server. You don't need that part. What you need is storing username and password on the client and send it with every request. You don't need more to do this than HTTP basic auth and an encrypted connection:
Figure 1. - Stateless authentication by trusted clients
You probably need an in-memory auth cache on server side to make things faster, since you have to authenticate every request.
Now this works pretty well by trusted clients written by you, but what about 3rd party clients? They cannot have the username and password and all the permissions of the users. So you have to store separately what permissions a 3rd party client can have by a specific user. So the client developers can register they 3rd party clients, and get an unique API key and the users can allow 3rd party clients to access some part of their permissions. Like reading the name and email address, or listing their friends, etc... After allowing a 3rd party client the server will generate an access token. These access token can be used by the 3rd party client to access the permissions granted by the user, like so:
Figure 2. - Stateless authentication by 3rd party clients
So the 3rd party client can get the access token from a trusted client (or directly from the user). After that it can send a valid request with the API key and access token. This is the most basic 3rd party auth mechanism. You can read more about the implementation details in the documentation of every 3rd party auth system, e.g. OAuth. Of course this can be more complex and more secure, for example you can sign the details of every single request on server side and send the signature along with the request, and so on... The actual solution depends on your application's need.
Cookies are not for authentication. Why reinvent a wheel? HTTP has well-designed authentication mechanisms. If we use cookies, we fall into using HTTP as a transport protocol only, thus we need to create our own signaling system, for example, to tell users that they supplied wrong authentication (using HTTP 401 would be incorrect as we probably wouldn't supply Www-Authenticate to a client, as HTTP specs require :) ). It should also be noted that Set-Cookie is only a recommendation for client. Its contents may be or may not be saved (for example, if cookies are disabled), while Authorization header is sent automatically on every request.
Another point is that, to obtain an authorization cookie, you'll probably want to supply your credentials somewhere first? If so, then wouldn't it be RESTless? Simple example:
You try GET /a without cookie
You get an authorization request somehow
You go and authorize somehow like POST /auth
You get Set-Cookie
You try GET /a with cookie. But does GET /a behave idempotently in this case?
To sum this up, I believe that if we access some resource and we need to authenticate, then we must authenticate on that same resource, not anywhere else.
Actually, RESTfulness only applies to RESOURCES, as indicated by a Universal Resource Identifier. So to even talk about things like headers, cookies, etc. in regards to REST is not really appropriate. REST can work over any protocol, even though it happens to be routinely done over HTTP.
The main determiner is this: if you send a REST call, which is a URI, then once the call makes it successfully to the server, does that URI return the same content, assuming no transitions have been performed (PUT, POST, DELETE)? This test would exclude errors or authentication requests being returned, because in that case, the request has not yet made it to the server, meaning the servlet or application that will return the document corresponding to the given URI.
Likewise, in the case of a POST or PUT, can you send a given URI/payload, and regardless of how many times you send the message, it will always update the same data, so that subsequent GETs will return a consistent result?
REST is about the application data, not about the low-level information required to get that data transferred about.
In the following blog post, Roy Fielding gave a nice summary of the whole REST idea:
http://groups.yahoo.com/neo/groups/rest-discuss/conversations/topics/5841
"A RESTful system progresses from one steady-state to the
next, and each such steady-state is both a potential start-state
and a potential end-state. I.e., a RESTful system is an unknown
number of components obeying a simple set of rules such that they
are always either at REST or transitioning from one RESTful
state to another RESTful state. Each state can be completely
understood by the representation(s) it contains and the set of
transitions that it provides, with the transitions limited to a
uniform set of actions to be understandable. The system may be
a complex state diagram, but each user agent is only able to see
one state at a time (the current steady-state) and thus each
state is simple and can be analyzed independently. A user, OTOH,
is able to create their own transitions at any time (e.g., enter
a URL, select a bookmark, open an editor, etc.)."
Going to the issue of authentication, whether it is accomplished through cookies or headers, as long as the information isn't part of the URI and POST payload, it really has nothing to do with REST at all. So, in regards to being stateless, we are talking about the application data only.
For example, as the user enters data into a GUI screen, the client is keeping track of what fields have been entered, which have not, any required fields that are missing etc. This is all CLIENT CONTEXT, and should not be sent or tracked by the server. What does get sent to the server is the complete set of fields that need to be modified in the IDENTIFIED resource (by the URI), such that a transition occurs in that resource from one RESTful state to another.
So, the client keeps track of what the user is doing, and only sends logically complete state transitions to the server.
As I understand, there are two types of state when we are talking about sessions
Client and Server Interaction State
Resource State
Stateless constraint here refers to the second type in Rest. Using cookies (or local storage) does not violate Rest since it is related to the first.
Fielding says: 'Each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client.'
The thing here is that every request to be fulfilled on the server needs the all necessary data from the client. Then this is considered as stateless. And again, we're not talking about cookies here, we're talking about resources.
HTTP transaction, basic access authentication, is not suitable for RBAC, because basic access authentication uses the encrypted username:password every time to identify, while what is needed in RBAC is the Role the user wants to use for a specific call.
RBAC does not validate permissions on username, but on roles.
You could tric around to concatenate like this: usernameRole:password, but this is bad practice, and it is also inefficient because when a user has more roles, the authentication engine would need to test all roles in concatenation, and that every call again. This would destroy one of the biggest technical advantages of RBAC, namely a very quick authorization-test.
So that problem cannot be solved using basic access authentication.
To solve this problem, session-maintaining is necessary, and that seems, according to some answers, in contradiction with REST.
That is what I like about the answer that REST should not be treated as a religion. In complex business cases, in healthcare, for example, RBAC is absolutely common and necessary. And it would be a pity if they would not be allowed to use REST because all REST-tools designers would treat REST as a religion.
For me there are not many ways to maintain a session over HTTP. One can use cookies, with a sessionId, or a header with a sessionId.
If someone has another idea I will be glad to hear it.
i think token must include all the needed information encoded inside it, which makes authentication by validating the token and decoding the info
https://www.oauth.com/oauth2-servers/access-tokens/self-encoded-access-tokens/
No, using sessions does not necessarily violate RESTfulness. If you adhere to the REST precepts and constraints, then using sessions - to maintain state - will simply be superfluous. After all, RESTfulness requires that the server not maintain state.
Sessions are not RESTless
Do you mean that REST service for http-use only or I got smth wrong? Cookie-based session must be used only for own(!) http-based services! (It could be a problem to work with cookie, e.g. from Mobile/Console/Desktop/etc.)
if you provide RESTful service for 3d party developers, never use cookie-based session, use tokens instead to avoid the problems with security.

Way to maintain a session in a REST application

We have a REST application that is utilized mostly by applications that dont need to maintain their state, so till date we have been quiet "RESTFUL" without maintaining a state. We use the Private/Public (similar to Amazon) for authentication.Currently the client passes the credentials for every request
Now we have a new requirement where we have to maintain the state (or conversation).The client can be a Rich application or a hand held device .I am trying to comeup with the best way to implement the state .Should we pass on a session Id and maintain that ID ..is that the best and the only solution ?
Passing on a session ID is not the only way and not the best way to maintain conversational state. The best way, if you have a RIA is to maintain the state on the client itself, where it belongs, as some of the comments suggest. This means still sending the credentials every request.
Re-authentication on every request is the only way, and if you feel that there's a performance hit on the server, the server can (as suggested) cache the result of an authentication request for a period of time. Digest authentication could help avoid caching responses by cryptograpically signing the tokens going over the wire.
If that's not good enough you could use something akin to Google ClientLogin, and giving the client an encrypted token that can be verified without needing to ask an authorization, and without passing the user's real credentials over the wire. Google themselves this by doing the login over https, and then using the generated tokens over http. It's open for replay attacks for the lifetime of the token.