0

I am developing a small REST-webservice for non critical data which will mainly be accessed by a smartphone application. For limiting the access of the users to their individual data (the authorization does not need groups or roles), I need to implement some sort of basic authentification.

As the service will be accessed over HTTP, using HTTP-Authentification seems to be no good idea as the username and password will be sent in cleartext on every request and need to be stored on the client device.

Thus, my idea was to implement authentification the following way:

  1. The user logs on using a login method of my webservice passing their username / password
  2. This method checks the validity of the username / password combination (based on a database containing salted and hashed passwords)
  3. If the login is successful, the id of the user (primary key of the database table) is stored in the session as an attribute
  4. In the following requests, this attribute is used to authentificate the user

In code, my login method would look like the following:

User user = this.authentificate(username, password);
HttpSession session = request.getSession(true);
if (user != null)
   session.setAttribute("UserId", user.getId());
else
   session.invalidate();

Afterwards, I would be able to authentificate the user based on the session:

int userId = (int) request.getSession().getAttribute("UserId");
User currentUser = getUserById(userId);

Can this approach be considered as "secure" (no easy session highjacking possible - as far as I understood https://stackoverflow.com/a/5838191/232175 , the attributes' values won't leave the server)?
Are there any downsides or alternatives?

Community
  • 1
  • 1
Matthias
  • 12,053
  • 4
  • 49
  • 91
  • Wouldn't Evil Hackers™ be able to get in as arbitrary users by spoofing cookies with random UserIds? – Wug Oct 18 '12 at 15:06
  • As described in the link, this does not seem to be possible as only a session id is sent to the client (quite long, so not very easy to guess) while the actual data seems to stay on the server. The server will then manage the mapping between the sessionid and the session attributes. But I am not 100% sure about this, thus my question ;-) – Matthias Oct 18 '12 at 15:10
  • "Quite long" and "Java `int`" are contradictory statements. Also, if they're sequential, the value of 0 or 1 will probably be the first account created on the system (i.e. the admin account). Furthermore, all you'd need to know to steal someone's account would be their user id, which I'm assuming can't be changed. If anyone did discover your ID, you'd be screwed forever. – Wug Oct 18 '12 at 15:18
  • 1
    @Wug - the user id is an int, but the session id is not. Your comment would be correct if he was storing the user id in a cookie, but that's not what he's doing. – Eric Petroelje Oct 18 '12 at 15:23
  • 1
    The session id would have to be sent securely (i.e. using HTTPS, using cookie config "secure" and "httpOnly". Otherwise your session id can be stolen e.g. over unencrypted wifi, and then your session id can be spoofed. – beny23 Oct 18 '12 at 15:39
  • @EricPetroelje: make sure you read the code provided. I know that using session keys is safe, but that's not what he's doing. He's storing the user ID, and then to authenticate, reading the user ID from the session (from the cookie) and authenticating as that user without a password. See step 3 of his auth process: "If the login is successful, the id of the user (primary key of the database table) is stored in the session as an attribute" – Wug Oct 18 '12 at 15:45
  • @beny23: Yes, I guess this could be a problem. Nevertheless, I don't see any alternative as HTTPS is not available in my context. As the data stored in the service is not very critical, I guess this risk needs to be accepted (as it exists on every website / webservice not secured with HTTPS). I agree that plain HTTP webservices are never secure but I wanted to verify that I don't introduce additional, avoidable risks through my method. – Matthias Oct 18 '12 at 16:23
  • @Wug: "from the session (from the cookie)" - I don't read it from the cookie, I read it from the session. The cookie only contains the id of the session. As the session is managed by the application server, the session attributes lay inside the application server. So the UserId won't leave the server; only the key identifying where in the session storage of GlassFish it is stored. – Matthias Oct 18 '12 at 16:24
  • Guess that clears that up then. Yes, as long as you're not storing this information where it can be tampered with it's fine. – Wug Oct 18 '12 at 17:18

1 Answers1

2

With regard to storing the user id in the session, I think that is OK, but you have another problem.

First, I would assume that the login method would be over HTTPS, otherwise the username and password would be sent in clear text to the login method and you are right back to the same problem you had before.

Second, if the login method were over HTTPS, then the session cookie would be an HTTPS cookie and all other API calls would also need to be over HTTPS. If subsequent calls were over HTTP, they would get a new session cookie and the user id would be unavailable in that session.

If you really want secure authentication without HTTPS, you would need to use a shared secret signing scheme (e.g. HMAC) or an asymmetric signing system like RSA to have the client sign requests and then validate those signed requests server side.

Eric Petroelje
  • 59,820
  • 9
  • 127
  • 177
  • Thanks for your response - no the login would be done using plain HTTP, too as the infrastructure required for HTTPS is not available. I know that at some point, username and password will be transferred in clear text when only using HTTP so I try to minimize this to only happen at the first start of the application. How would I handle account creation using HMAC? At some point, I need to transfer the password to the server (which will happen in plain text as HTTPS is not available as said), don't I? – Matthias Oct 18 '12 at 16:13
  • @winSharp - With HMAC you need to store the key on the server and associate it with a user account, so at some point you would need to generate it and display it to the user - maybe at account creation, or maybe have a screen in the app to generate an "API Key" (basicly an HMAC secret). With RSA though this is not necessary - the user could generate a key pair on their PC and just send you the public key, keeping the private key to themselves. – Eric Petroelje Oct 18 '12 at 16:33
  • Ok, but the users certainly don't want to type in or even remember this key when they log on from a different machine / smartphone. Thus, I would need to implement some kind of key retrieval mechanism which would only bring me to where I started. I just looked a bit into OAuth which seems to provide similiar possibilities - however, it appears a bit like an overkill in my scenario to me. – Matthias Oct 18 '12 at 16:45