Back in February I finally got to research and work around an issue that had been driving me nuts. I have an app which requires login, and uses CI sessions. Using one particular page, after a while my AJAX calls will fail because I am no longer logged in. Reload the page, yep, I'm logged out.
Turns out, this is a known issue, going way back:
CodeIgniter regenerates a new session ID periodically, to prevent session ID hijacking (session fixation attacks). At some point my session ID will change, and my session will effectively expire because the AJAX requests aren't setting the new session ID in my browser.
https://github.com/EllisLab/CodeIgniter/issues/154
This goes beyond AJAX, though. If you want the session to stay open over time, e.g. a Keep Me Logged In functionality, you will also see this problem: when you open the site tomorrow, your session ID is out of date and you're not Keeping Logged In at all.
Fortunately, the fix for this is not difficult.
Session Expiration & Session ID Regeneration
Open up config.php and look for these two session variables.
The sess_expiration setting, defines how long a session is good (idle time since last hit).
The sess_time_to_update setting, defines how often your session ID will be regenerated.
$config['sess_expiration'] = 86400 * 30; // 30 daysOur problem is the session ID regeneration. We can effectively disable this by making sess_time_to_update very, very long:
$config['sess_time_to_update'] = 300; // 5 minutes
// sessions are good for 30 days, and IDs will change every year
$config['sess_time_to_update'] = 86400 * 365;
Problem solved. I only need to login after 30 days of idle time, and even using AJAX-heavy pages without
Consequence: Session Fixation
Disabling session ID regeneration does have a consequence for security, though. Now that your session ID doesn't change, it's hypothetically possible for someone to snag your session ID and use it indefinitely (well, for a year if you set it as above).This can be mitigated by a few other arrangements:
Shorten the session expiration and regeneration time. Do they really need a session to be good for 30 days? Would 7 days suffice? How about 3 days? The shorter it is, the less time you give a sniffer to try hijacking your session before finding it already expired.
Encrypt the cookies! Set sess_encrypt_cookie to TRUE and set a random encryption_key so thesession IDs can't be intercepted in the first place. Do a Google search for "codeigniter encryption key generator" and take your pick.
Enable user agent matching. The sess_match_useragent setting enables a check on your session, that you're using the same browser as you were when the session opened. User agent strings can be faked, but this does increase the "cost" of brute forcing or hijacking sessions, as the hacker must try the session key several times as they guess browsers.
Enable IP address matching. The sess_match_ip setting enables a check that your IP address hasn't changed since your session was last used. This one may not be appropriate if your ISP routes traffic through changing proxy servers (satellite Internet, America Online) and most of us have dynbamic IP addresses that change every few days. But, if your use case is access from a fixed IP address such as an office intranet, or you can tolerate logging back in after your reset your home router, this can provide a significant layer of security.
Use SSL. This isn't always possible, but when it is, intercepting sessions is impossible. If you use this and also cookie encryption, then intercepting sessions is doubly impossible.