Laravel session id changes with each request - php

I have a Laravel 5.0 site where the frontend JS makes a lot of ajax calls to the backend Laravel code. I've noticed that on each ajax request I'm getting a new "laravel_session" cookie value in the response everytime. I'm guessing that this is some security mechanism to protect against session hijacking.
However I think this is causing an issue with my site, as my ajax calls often happen in parallel, not sequentially. I don't wait for the response before firing the next call.
Consider this scenario
. Ajax call 1 - request - laravel_session cookie = '1234'
. Ajax call 1 - response - laravel_session cookie = '2345'
. Ajax call 2 - request- laravel_session cookie = '2345'
. Ajax call 3 - request- laravel_session cookie = '2345'
. Ajax call 2 - response - laravel_session cookie = '3456'
. Ajax call 3 - response - session not longer valid
Is there any way around this?
I should also note that sessions are set to expire in the config/session.php as
'lifetime' => 120,

You are right it is a security mechanism. To disable it for testing, in Kernel.php comment out this line:
\App\Http\Middleware\EncryptCookies::class
Then you will see the session ID in your cookie viewer and it doesn't change.
You can Google for HTTP encrypted cookies to learn about the practice. There is an ongoing debate if this old practice is necessary now that we use HTTPS on every website.

Your domain is invalid. You need to look at config.session.domain and config.session.path.

The same issue happened with me and it was later identified that I was using
protected $middleware = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class
];
protected $middlewareGroups = [
'web' => [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class
]
]
in both $middleware and in $middlewaregroups because of which it was creating a new session id in movement between different routes.

I had the same issue, I tried a lot of solutions and nothing worked for me.
My case:
The token keeps changing on every request only when the session driver is set to database, and it works just fine on file and Redis driver.
After a lot of debugging, I found that the issue was not with session config, it was from the payload column in the session table in the DB.
I changed the payload column from text to longText, and it worked!

There are some important things about sessions. First is cookie time. If your Laravel app's timezone is UTC but your computer's timezone is +3 then if you set your cookie lifetime 120 (two hours) then cookie will deleted by browser immediatelly. You must increase your cookie lifetime.
Other option is encryption. Cookies are always encrypted. If you set encrypt=true in sessions.php file storage/framework/sessions folder will be encrypted. Sometimes this causes problem. If session doesn't keep then try to set encrypt to false. After that you can see session files are unencrypted and they have 'serialized' text. Then you can see your session variables in there.
Other option is domain variable in sessions.php file. You must set it correctly or leave it null. Domains must not have http(s):// at first. Write only domain in there (for example yourdomain.com, yourdomain.test, yourdomain.host, www.yourdomain.com, subdomain.yourdomain.com etc...).
Other option is about driver. If you set it to database then you must be sure your table columns have enough size for storing big session data. If you set it to file then you must be sure that storage/framework/sessionsĀ folder is writable and readable.
And there is a "small" (I think so important) trick. Don't use general keywords in session. For example don't use 'token' key. Use specific names for session. This is wrong: session(['token' => $result->token]), but this is better: session(['backend_remote_token' => $result->token])
Rock'n roll...

Related

codeigniter unsetting session works unexpectedly

I submit form to controller/complete action, set
$this->session->set_userdata('success', 3);
and then redirect to index action with redirect('controller', 'refresh');.
In my view I get
$success = $this->session->userdata('success');
do some work and then
$this->session->set_userdata('success', 0);
And it works fine, but when I reload page (it is an index action), I still get in $success 3, not 0. What am I missing?
I have seen many problems with codeigniter DB Session, and thus refuse to use it, to include the session not actually properly updating.
If you are interested I created a PHP Session based class that acts as a replacement, it benefits from backward compatability, but also a much easier way of using it.
Check out my Gist: https://gist.github.com/chazmead/1688becbcf11f897e962
To install you will need to replace the CI Session config in application/config/config.php to:
$config['session'] = (object)array(
'UID' => 'MY_SESSION_KEY',
'sess_expiration' => 7200,
'match_ip' => False,
'match_user_agent' => False
);
Then install the file to application/models/session.php
then instead of loading the CI session, just load this session model.
Using this is very easy, just assign variables to the session and it saves automatically, it also locks and unlocks the session so that async requests don't get locked up (which is a problem with PHP sessions)
For full backward compatability you may need to use $this->session = &$this->Session after loading the new model, otherwise you will have to make sure your calling session using Session (Uppercase S) as this is how CI models work. or install as a library instead..
The codeigniter by default managing session in COOKIE, more info
why the cookie value is not updated at once when i submit the form?
CI also provides setting to store session data in database table, if you store session in table this would work fine.
http://ellislab.com/codeigniter/user-guide/libraries/sessions.html

PHP Session cookie not saving, unable to access session data

I've this little problem: PHP is not saving the cookie to my (cookie allowing) browser, other sites are fine but this one fails to save the session id in the cookie, ergo an inability to access necessary data.
The index page does a
require("includes/functions.php");
which successfully requires my functions file:
session_name('login');
// Starting the session
$expiretime = 60*60*24;
session_set_cookie_params($expiretime);
// Making the cookie live for 1 day
session_start();
However, the login cookie is not saving (checked via Firebug) and I've no reason why. Thanks for the help
Try displaying the session cookie parameters to make sure they are ok by running after session_start:
var_dump(session_get_cookie_params());
If path (or domain) doesn't match the prefix of your web app path, then you might have to set it explicitly:
session_set_cookie_params($expiretime, '/');
or
session_set_cookie_params($expiretime, '/myapp/');

What is the best way to make "remember me" under php when using native sessions?

Previously i was creating additional cookie "rememberme" with unique hash, that was stored in the database, mapped to the user id.
If user had such cookie - website tried to find it's value in database, and if it was found session was setting up.
Later, developing new project i thought that it is maybe not very secure to generate this unique hash by myself, and keeping two cookies (native "PHPSESSID" + my "rememberme") for one operation (user identification) is overkill.
Maybe there is a way to setup not global session lifetime, but to setup it individually for different user sessions... or maybe it is better to keep user sessions in the database, mapped to the userid?
UPDATE 1
I thought if it is so hard to make "remember me" button, we can go another way - to make "Not my computer button". Idea is to set default cookie_lifetime for a week in php.ini (for example), and if user checkes this checkbox - we will set cookie_lifetime into zero using session_set_cookie_params function.
So, 1st question is - will session_set_cookie_params affect other users cookies (in documentation it is said, that session_set_cookie_params options will have effect until php process will be executing)
2d question is that if session_set_cookie_params is not affecting global settings, will session regeneration affect users, that don't want to keep a long-life cookie?
UPDATE 2: [Question 1 answer]
Just tested session_set_cookie_params function.
I wrote a script, that sets session cookie lifetime into zero using session_set_cookie_params and then executing for 30 seconds:
if ($_GET['test']) {
session_set_cookie_params (0);
while (true) {
sleep(1);
}
}
session_start();
So, in first browser i just started this script with ?test=1 parameter, just after that (while this script was executing) i started this script without parameters in the second browser. The answer is no - second browser's cookie was not affected. It had lifetime, that was specified in php.ini
UPDATE 3: [Question 2 answer]
Then, i've tried to check if regeneration affects session cookie lifetime, that was set by session_set_cookie_params.
Yes, it affects. If i set session cookie with customized lifetime, that was set by session_set_cookie_params, and then call session_regenerate_id(), cookie will have lifetime, set in php.ini
But, if we set session_set_cookie_params (0) before calling session_regenerate_id(), our cookie will have correct lifetime.
So, that's it! That was easy! 8)
Thank you, ladies and gentlemen!
If you want to do this only using sessions you can do the following if the user wants to be remembered:
if((isset($_POST['remember_me']) && $_POST['remember_me']) || ($_COOKIE['remember_me']) && $_COOKIE['remember_me'])) {
// store these cookies in an other directory to make sure they don't
// get deleted by the garbage collector when starting a "non-remeber-me"-session
$remember_me_dir = ini_get('session.save_path') . DS . "remember_me_sessions";
// create the directory if it doesn't exist
if (!is_dir($remember_me_dir)) {
mkdir($remember_me_dir);
}
// set the php.ini-directive (temporarily)
ini_set('session.save_path', $remember_me_dir);
// define lifetime of the cookie on client side
$expire_cookie = 60 * 60 * 24 * 30; // in seconds
session_set_cookie_params($expire_cookie);
// lifetime of the cookie on server side
// session file gets deleted after this timespan
// add a few seconds to make sure the browser deletes
// the cookie first.
$garbage_in = $expire_cookie + 600; // in seconds
// set the php-ini directive for the garbage collector of the session files.
ini_set('session.gc_maxlifetime', $garbage_in);
// send an additional cookie to keep track of the users
// which checked the 'remember_me' checkbox
setcookie('remember_me', 1, time() + $expire_cookie);
}
// now we are ready to start the session
// For all the users which didn't choose to check the 'remember_me' box
// the default settings in php.ini are used.
session_start();
Here you can read more about the session related php.ini-directives
As it was so hard to make "remember me" checkbox functionality, i came to another way, using only one cookie.
PREPARATION
1) I've prepared a form with three inputs:
"login" input [type=text]: user's login
"password" input [type=password]: user's password
"not my computer" input [type=checkbox]: that will tell us to use session cookie with lifetime = 0 (cookie must be deleted when browser will be closed)
2) I've set session.cookie_lifetime = 100500 to keep long-life cookies by default.
COOKIE SETUP
So, after user submits the form, we check - if he has selected to use short sessions - we call session_set_cookie_params(0) before setting session cookie to him (before actually using session_start()).
COOKIE REGENERATION
Then, when we need to regenerate session cookie, we can also do this easily with session_regenerate_id() function.
But we need to remember, that this function will re-set session cookie lifetime from php.ini by default.
So, we need also to call session_set_cookie_params() before regenerating a cookie.
BTW, You can store custom session cookie lifetime in $_SESSION.
It will look like this:
// Form handling, session setup
if ($_POST['not-my-computer']) {
session_set_cookie_params(0);
session_start();
$_SESSION['expires'] = 0;
}
// Session regeneration
if (isset($_SESSION['expires'])) {
session_set_cookie_params(0);
session_regenerate_id();
}
Details for this answer (and more deep explanations) you can find in the question text (while i was testing, i added answers/tests results there)

CakePHP keeps logging me out

Recently i have made three Cake Apps and all three share this problem. The config is mostly stock and i use this as the session options.
Configure::write('Session', array(
'defaults' => 'php',
'cookie' => 'test'
));
After lots of googling everyone just suggests that the security level is too high, but i have never changed this value, it's:
Configure::write('Security.level', 'medium');
Edit: I have also tried with low security and no change.
I am only using basic auth to check if the user is logged in or not.
After logging in the cookie is set to expire three hours later and the expire date doesn't update until I log in again, is this normal?
I cant seem to replicate the problem at all, sometimes I will log in and the very next click will log me out again and other times it will last a while.
I am using Chrome on Windows 7 and there is no AJAX on the website.
Any ideas? Thanks.
Are you using Ajax. Is the problem only happening in IE?
IE uses a different Browser Agent string for Ajax calls to the browser itself. For extra security, Cake checks the browser agent and, in the case of IE, thinks another browser is trying to hijack the session as the agent is different.
You can disable this check with:
Configure::write('Session.checkAgent', false);
After running into the same problem I've found that this was caused by the Session.cookieTimeout value. Although the php session was still valid, the expiration date on the session cookie does not get refreshed.
This is now my session config
Configure::write('Session', array(
'defaults' => 'php',
'timeout' => 30, // The session will timeout after 30 minutes of inactivity
'cookieTimeout' => 1440, // The session cookie will live for at most 24 hours, this does not effect session timeouts
'checkAgent' => false,
'autoRegenerate' => true, // causes the session expiration time to reset on each page load
));
the problem is with sessions:
First check ur 'phpinfo();'
check if the sessions are file based.
if yes, go through the process.
create a new script file(php) which contains only this code:<?php var_dump(session_save_path());?>
run it if you get null or empty string then go for this process:
first create a directory in your root folder name it 'xyz' or whatever u want.
make it writable i.e. chmod 777.
go to the script where you start sessions and before starting the sessions change your session_save_path to the newly created directory. i.e.: session_save_path('pathToxyz');
and then you r done.
if in case the sessions are set as memory: no configuration is required. they just use system memory. in that case you would never have got in to this problem.
You are not the only one having issues with CakePHP sessions on Chrome browser.
Pixelastic fellow coder suggests the following fix, quote :
Just create file named session_custom.php in app/config/, drop the following lines in it:
// Killing this config that was causing so much trouble with Chrome
ini_set('session.referer_check', '');
// No session id in url
ini_set('session.use_trans_sid', 0);
// Using custom cookie name instead of PHPSESSID
ini_set('session.name', Configure::read('Session.cookie'));
// Cookie like time, depending on security level
ini_set('session.cookie_lifetime', $this->cookieLifeTime);
// Cookie path
ini_set('session.cookie_path', $this->path);
Then set Configure::write('Session.save', 'session_custom'); in your core.php file.

Using PHP $_COOKIE to manage session vars

Due to server settings I am having to use $_COOKIE instead of $_SESSION to manage session vars for a project.
On my search form I set an initial cookie but am unclear whether this is helpful or needed?
setcookie('NOSG', 'oHai', time()+7200, '/', 'some.org');
Each time the search results page loads I iterate over the cookies and back date the ones I need to clear and then set the new values like so:
if ($board) {
foreach ($_COOKIE as $k => $v) {
if (preg_match('/boa_/', $k)) {
setcookie($k, '', time()-3600, '/', 'some.org');
}
}
foreach ($people as $p) {
setcookie('boa_'.$p->ID, $p->whatever, time()+7200, '/', 'some.org');
}
}
Mostly this is used for making sticky selections in multi-line <SELECT> inputs.
Is this approach sound? I have rarely used $_COOKIE for anything.
// EDIT 1:12 PM GMT-06:00
All of the comments and answers are focused on fixing sessions. I assume this is because there is some reason the method suggested is NOT sound? The question asked is about using $_COOKIE to remember form settings. Would anyone care to respond as to why the method I am using is or is not appropriate to the problem?
The error
Permission denied. session.save_path is set to /var/lib/php/session PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (/var/lib/php/session) in Unknown on line 0
Is due to an error on the part of your host/system administrator. They should set the permissions on /var/lib/php/session to 777 so it is writable by all users. If they are using something that executes your PHP script as your user, the data is still safe because your user will own the session data file so no one else can view or modify it.
Alternatively, you can change the session save path on the fly to a directory under your control.
If you were to have a common file that initiated your session, add this before session_start():
session_save_path('/home/yoursite/sessions');
// or
session_save_path($_SERVER['DOCUMENT_ROOT'] . '../sessions');
// or, an alternate method
ini_set('session.save_path', '/home/yoursite/sessions');
session_start();
Then just created that folder and set the permissions appropriately so it is readable/writable by your user only.
Technically all a session is, is a text file (OK, you can hold the data in a database as well) containing variables that's identified by a value held in a cookie (or the address bar).
It wouldn't be impossible to recreate the functionality within PHP using things like setcookie(), serialize() and file_put_contents() writing to a folder outside the web tree ... though you might also need a Cron job to schedule garbage collection (to be fair, PHPs native session GC doesn't seem to be spectacular).
You'd just need to create a custom session handling object and set the "session" id for it in a cookie exactly the same as if you were using normal session handling - except instead of using $_SESSION you'd use you Session::get() and Session::set() methods.
If you keep the API clean then, at a future date if you manage to get session handling enabled on the server, you'd only need to tweak your session handling object and it wouldn't affect the rest of your program code - it's probably a good idea to abstract away then session handling anyway.
None of the respondents addressed my question: Is using $_COOKIE to store session data a sound method?
Experience has taught me what they would not. Not all browsers handle cookies in the same way. For instance Internet Explorer has limits per domain on the number of cookies: http://support.microsoft.com/kb/941495
So the answer is- $_SESSION is superior to cookies as it is handled by PHP in the same manner for all browsers.

Categories