3

The Situation:

  • A java EE web application with user authentication based on username/password
  • Password verification is not done by the application itself. It uses HttpServletRequest.login() and the security-realm is defined in the application server.
  • The application uses authorization (@RolesAllowed annotation)
  • The application allows the user to be remembered, so he doesn't need to authenticate every time

I think this are quite common requirements for web applications, but the last requirement is not that easy to achieve, and I haven't found a standard way of implementing this. I like to show my ideas and explain why I think they are not perfect.

1 Just keep the HttpSession open
Actually this was my preferred way in the first place. I thought that using HttpSessioin.setMaxInactiveInterval() would do the trick. Basically it does but if the Sessions are not cleaned up properly and you have a lot of users this could be resource problem. Here my own question to show that cleaning up a HttpSession is not easy all the time.

2 Use a "remember me" cookie
Why not just generate a UUID and send it as cookie and than check for it when the HttpSession is new. This works pretty good if the only thing the security realm is used for is to check username/password. If authorization or functions like getUserPrincipal() are used, then it is not possible. I haven't found a way to use HttpServletRequest.login() or a similar function with a token instead of a password.

3 Use a "remember me" cookie and use my own authorization
Well, sure, this is possible, but I like the easy way to restrict access to some beans or methods. It makes it harder for me to implementing something where a user could access something he shouldn't.

4 Use a "remember me" cookie with the password in it
Stupid! Next!

5 Use a "remember me" cookie and keep the password
The idea is to remember the password and a relation to to the cookie, so the HttpServletRequest.login() could be used with the password. This is the method explained in this Answer: https://stackoverflow.com/a/5083809/210380
I think this method has a big problem: Never store passwords unencrypted
One could think about just keeping the passwords in memory, but I don't like that either. The application could be used anywhere and I don't want to be responsible if all passwords of a company are leaked because someone got temporally access to the server and made a memory dump.

My current solution
Based on these thoughts I came up with my own solution. I'm using two cookies. The first is just a "remember me" cookie with the String representation of a UUID. This UUID is also remembered in memory or a database together with the username. The second cookie also contains a String representation of a UUID and is used to encrypt the password. The encrypted password is remembered together with the UUID of the first cookie in a database or memory. The UUID from the the second cookie is not kept. Not in a database nor in memory. To encrypt and decrypt the user password I'm using StandardPBEStringEncryptor from jasypt.
When a user tries to reauthenticate with this cookies I read them both, search for the username and the encrypted password based on the first cookie, decrypt the password with the second cookie and use HttpServletRequest.login() with username and password. Then I delete the encrypted password stored on the server, and restart the process with two new UUIDs.

The questions

  1. Is there really no standardized solution for this?

  2. Are there any security problems in my solution I don't see?
    e.g. could it be unwise to encrypt the password with a new key on re-authentication

  3. Is StandardPBEStringEncryptor a good choice for this task?

  4. Is my solution overkill and I'm wasting my time?

Thanks

Community
  • 1
  • 1
raffael
  • 2,427
  • 4
  • 26
  • 42

1 Answers1

0
  1. There's really no standard for "remember me" in the servlet API.
  2. I believe your solution is more vulnerable to cookie stealing, since your second UUID is used to encrypt the password and is stored in a cookie. This answer shows what is usually kept in a login cookie.
  3. Is two way encryption really necessary? One way encryption is much simpler and easier to handle. Depending on you application security requirements, anything above SHA-512 is a suitable hashing algorithm.
  4. I'd recommend you take a look into Apache Shiro. It supports remember me, salted password hashing with multiple algorithms (one way only, but I'm not sure) and @RolesAllowed-like security interceptors.

If you go for Shiro, this tutorial is really thorough and complete. You could also check the offial documentation at shiro.apache.org

Community
  • 1
  • 1
andrepnh
  • 933
  • 8
  • 21