Forum OpenACS Development: Expiring logins requirements/design yet again ...

I just fixed a bug with login expiration on 5.0, which made logins expire within just minutes in the following situation:

- LoginTimeout is 0 (infinite logins never expire)
- The "Remember me" checkbox is not checked

I have fixed this by sacrificing a new security feature for usability, but wanted to post here with a little explanation ...

REQUIREMENTS

The design goal is to have more server-side control over authentication cookies. Particularly, logins should be expirable as per the following:

- the session is inactive for more than x minutes (when you haven't checked the 'Remember me' checkbox, or the option is not available)

- Up to a maximum of LoginTimeout (typically between 2 and 24 hours, depending on the level of security desired; Yahoo lets users pick a range of 2-8 hours)

- However, if the password is changed, all sessions and logins on other browsers than the one changing the password should expire immediately (within a few minutes)

- If the account is closed (e.g. banned), all sessions or logins for that account should expire imemdiately (within a few minutes).

On top of this, there are further security measures for handling authentication over HTTPS.

DESIGN

We have two cookies:

- ad_session_id is for the session, and includes information about the user_id and the login level. Login level is 0 = not logged in/authentication expired; 1 = authentication tip-top ok; 2 = authentication is tip-top okay, but your account is closed (e.g. banned). So only if user_id != 0 and login_level = 1 do we actually consider you officially and fully logged in.

The session cookie expires and is refreshed frequently.

It is expired by both server and client after "SessionTimeout" seconds (default value: 1200 = 20 minutes). When the session expires, we forget everything, including user_id.

It is refreshed much more frequently, though, namely when it is "SessionRenew" seconds old (default value: 300 = 5 minutes).

So if you keep hitting the site, the session will be refreshed every 5 minutes, meaning that the session will expire between 15 and 20 minutes after your last hit. And if you do keep hitting the site, then, after my fix above, you will stay logged in forever. Period.

As per the requirements above, my goal is the following changes:

1) if LoginTimeout is set (!=0), then this should be the maximum lifetime of your logged in session, regardless of whether you keep getting your session cookie refreshed. In other words, when refershing the session cookie, we need to check when you last authenticated, and if that's more than LoginTimeout ago, then we should issue a session cookie with user_id staying the same, but login_level = 0 (expired).

2) If the auth_token has change (which is our mechanism for expiring logins server-side, e.g. when changing password), we will also issue a new session cookie with the same user_id, but with login_level = 0 (expired).

3) If your account has been closed (e.g. banned), we'll issue a session cookie with same user_id, but with login_level = 2 (account closed).

So much for the session cookie. Now for the ad_user_login cookie.

The original idea was that this cookie will only get issued if you click "Remember me on this computer".

So if you visit the site with no session cookie, the ad_user_login cookie can be used to 'seed' the session cookie with a user_id from the ad_user_login cookie. If the ad_user_login cookie is expired, or the cookie's auth_token doesn't match the auth_token in the database (e.g. if the password has been changed), the session cookie's login_level is set to 0. If the account is closed, the session cookie's login_level is set to 2. Otherwise, the session cookie's login_level is set to 1, and the user is set to go.

One of the changes I made to the security system in 5.0 was to always create an ad_user_login cookie, even if you logged in without checking "Remember me". And then, whenever we refresh the session, we check that login cookie, including expiration, auth_token, and account status.

Then when you login without checking the "Remember me" box, instead of making the ad_user_login cookie be permanent, I set the login cookie to expire after LoginTimeout (defaults to 8 hours). Now, if you've set LoginTimeout to zero, it will expire immediately.

The problem with this design is that it kills the ability for a session to expire based on a certain period of inactivity.

Hence, some slight modifications to the design are required  for 5.1:

- include the login issue_time in the session cookie, so we can stop refreshing your session when we reach LoginTimeout, without having to set the ad_user_login cookie at all.

- include auth_token the session cookie, so we can expire your session server side, withouth having to set the ad_user_login cookie.

- check and verify time sine login issue time, auth_token, and account_status when refreshing the session cookie.

Thoughts?

/Lars

Collapse
Posted by Hazi Gharagozlou on
Lars,

Does your fix solve the following problem, if yes where is it?

I recently set LoginTimeout = 0 on an updgraded site (from 4.6.3 to 5.0.3). Once I log out manually, I am not able to login again (Password expiration message). I deleted cookies and tried other browsers to no avail. Finally I was able to login by updtating the apm_parameter_values.

Collapse
Posted by Lars Pind on
Hazi,

There are two issues:

1) the login page has expired (to prevent people from reusing your login page after you've logged out and left the site)

2) you're successfully logged in, but the login expires very quickly.

To my knowledge, I've actually fixed both of these.

/Lars

Collapse
Posted by Joel Aufrecht on
The fix should be in 5.0.4, due out any day now.
Collapse
Posted by Hazi Gharagozlou on
Lars,

I just checkout the 5.0.4-final version from cvs, and I am afraid to report that the login problem still there. Just to reiterate, I changed in the permissions of acs-kernel  LoginExpirationTime from 1200 to 0 and I get "The login page has expired. Please log in again." The only remedy is to change the record in apm_paramter_values.

Collapse
Posted by Joel Aufrecht on
Let's escalate this to a bug, instead of a forum discussion, so we have better tracking and can incorporate it into release managed.  Hari, could you file it, with a verbose repro case?  Lars, could you verify that your new code is indeed in 5.0.4?
Collapse
Posted by Lars Pind on
Ok. Change was on HEAD (5.1).

http://cvs.openacs.org/cvs/openacs-4/packages/acs-subsite/lib/login.tcl?r1=1.20&r2=1.21

if { $expiration_time < 30 } {
  	         # If expiration_time is less than 30 seconds, it's practically impossible to login
  	         # and you will have completely hosed login on your entire site
  	         set expiration_time 30
  	     }
This bug has been there since the beginning of times.

/Lars