Brief Summary
When I click a link from gmail, the cookies and sessions are lost. But if I copy the link in gmail and paste it in a blank tab, the cookies are retained!
Long Detail
At www.mydomain.com, i set cookies and PHP session with following options:
$myCookieSessionOptions = array(
'lifetime' => (time() + 60*60*24*363),
'path' => "/",
'domain' => "." . "mydomain.com",
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
);
session_set_cookie_params ( $myCookieSessionOptions ) ;
session_name("mySessionName");
session_start();
The above is the code both on page login.php and anotherpage.php.
On login.php when I login and set sessions, etc. the session_id() shows up as c7a9c180b767e889ad0161dc613aec41, for example.
When i access anotherpage.php in a blank tab and with some GET parameters (and my code does nothing to the session), i get the same session_id().
However, when the same link for anotherpage.php (along with the get parameters) is sent in an email, then I get a totally new session_id: 3fc7f8749ba6eb46ddd35a0db3a17589 for example.
And in the other tab, which had login.php, the session is lost, as a new session is created, obviously.
The question is if this behaviour is normal?? And this is not with gmail alone, obviously. From "anyotherdomain.com", when i click on a link to my domain, no cookies are sent!
Very weird! Is there any documentation on this behavior?
Any help will be appreciated
session auto start is Off. Checked in phpinfo
And there's no code before the above that does anything at all with the sessions
Thanks
Rajan
I figured it out! If I have samesite="none", the problem disappears
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
And tested it & it works fine.
As per the doc:
Strict
Cookies will only be sent in a first-party context and not be sent along with requests initiated by third party websites.
Related
Wondering if someone can provide some clarification on why this is behaving how it is when using samesite in a php session cookie.
example.com has the following :
session_name('Example_Login');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'domain' => '.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
session_start();
test.com has the following form posting to example.com :
<form method="post" action="https://www.example.com/" target="_blank" autocomplete="off">
<input type="hidden" name="username" value="demo_user">
<input type="hidden" name="password" value="demo_password">
<input type="hidden" name="signin" value="signin">
<button type="submit" name="submit">Login</button>
</form>
example.com receives the post and with php I use the $_POST variables sent to validate the login credentials and log the user in. With those values being valid, the user is not logged into example.com though. If, I change the samesite parameter on example.com's session cookie to 'lax' the posted form works as expected.
I did read up on the samesite parameter before adding it and I did not see anything that stuck out to me where it would affect posts/gets. What am I missing here? I don't see how the samesite parameter has ANY affect on what I am doing here. I sent a post from another domain, retrieve the variables, and do some logic with php... what does the samesite parameter for the session cookie have to do with anything here?
UPDATE:
I did some debugging. The post variables are sent and received fine, session is created on example.com and creates lots of $_SESSION vars, etc. I narrowed down the problem to a redirect that happens after the username/password is validated in php. If the user/pass is correct and the account exists I store user information in $_SESSION then I call the following in php :
header("Location: /main.php");
exit();
The redirect happens and upon reaching main.php $_SESSION is empty. All of its variables are gone. I echo'ed it and it shows the following :
Array
(
[user] => Array
(
[session] => 1
)
)
I switch the samesite parameter to 'lax'. Run the exact same debugging and $_SESSION is full of my user information as expected which was put there before the redirect.
I also changed my redirect to absolute as header("Location: https://www.example.com/main.php"); to see if that had an affect, but the problem still remains.
So, my question now is... when using samesite='strict' in my session... why is the session emptied after a redirect to a page on the same domain?
UPDATE 2:
I changed the session save path to another location specifically to debug and see what happens. When it reaches example.com it creates the session file and the values I added into it are there. When it reaches example.com/main.php (the redirect) it creates a brand new session file as seen above. My session settings and start are in their own file which is required first thing on these pages :
session_name('Example_Login');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'domain' => '.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
session_start();
So with samesite='strict' the above creates a new session, but with samesite='lax' it uses the same session file from the previous page. What gives? I am seeing where things are going wrong, but not why it is happening or how to fix it.
UPDATE 3:
Created a very simple test to demonstrate what is happening and why. See answer below. One can argue with me all day justifying why this works how it does, but I think the logic happening here is flawed.
SameSite=Strict means the cookie will not be sent on cross-site requests which includes cross-site POST requests and redirects triggered from the cross-site POST request.
SameSite=Lax is the correct option for your session cookie here. Being able to use Strict here is not better or more secure, it is too restrictive for this use case.
I've boiled this entire thing down to a simple test.
example.com has two pages :
test1.php
<?php
//session name
session_name('Test');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'domain' => '.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
session_save_path($_SERVER['DOCUMENT_ROOT'].'/sessions');
session_start();
//session stuff
$_SESSION['sessiontest'] = 'worked';
//cookie stuff
setcookie('testing', 'worked', ['expires' => 0, 'path' => '/', 'domain' => 'example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
//redirect to the other page
header("Location: /test2.php");
exit();
?>
test2.php
<?php
//session name
session_name('Test');
session_set_cookie_params(['lifetime' => 0, 'path' => '/', 'domain' => '.example.com', 'secure' => true, 'httponly' => true, 'samesite' => 'strict']);
session_save_path($_SERVER['DOCUMENT_ROOT'].'/sessions');
session_start();
echo '<pre>'.print_r($_SESSION,1).'</pre>';
echo '<pre>'.print_r($_COOKIE,1).'</pre>';
?>
test.com
go to test
If you start at test.com the session and cookie (created at example.com/test1.php) are empty at example.com/test2.php. This all has to do with the chaining and logic being used for samesite which in my opinion is flawed in this case. The session and cookie it is preventing are being CREATED on the site this is supposed to protect from the 'outside'. I'm sure someone will have some argument justifying this, but as far as I see it this whole thing was created to mitigate the results of bad coding... and in this case... is preventing legitimate code from working as it should. This example shows I am not 'using' anything from test.com... yet because of the redirect happening when you reach example.com/test1.php it sees the session and cookie created on it as more or less 'bad' when reaching example.com/test2.php because the chain started at test.com.
In my Cakephp application, i have a session cookie with the name 'my_cookie' and it contains some random value 'QSD5111AS552DNJK'.
I observed that the value is same for the cookie (Before login and After login also). If i want to change the cookie value after login, what are the steps i have to follow.
And my code in core.php file
Configure::write('Session', array(
'defaults' => 'php',
'cookie' => 'my_cookie',
'timeout' => 4000
));
Please help me in this issue for getting more clarification.
I guess what you want to do is prevent session fixation, in that case it should be noted that CakePHP already does this for you out of the box. When using the authentication component, the session is being renewed before the authenticated user data is being written to it, and after the user data is being deleted on logout.
See
Source > AuthComponent::login()
Source > AuthComponent::logout()
For the sake of completeness, you can always renew the session manually, either via the session component in case you are in a controller
$this->Session->renew();
or by using the CakeSession class directly
App::uses('CakeSession', 'Model/Datasource');
CakeSession::renew();
At the end of my registration script I set a cookie of 'loggedin' like so
setcookie("loggedin", $username, time()+60*60*24*30 );
And then just redirect back to the home page.
I'm trying to echo out the contents of that cookie. I can see it has been created when I go right click > page info > security > view cookies.
The name of the cookie is there, 'logged in' with contents set to as the username I register as. But when I do something like
print_r ($_COOKIE);
Nothing shows.
Doing a
var_dump($_COOKIE);
Gives
array (size=0)
empty
Why might this behavior be occurring if I can see that the cookie is indeed there when I follow the previous steps mentioned?
Usually it can be caused because you don't have the domain/path item set. Try Using:
setcookie("loggedin", $username, time()+60*60*24*30, '/', $domain);
you should store cookies BEFORE any output
because cookies are contained in http header, so if you start output of your html page and store cookies after that - nothing will be stored
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.
Cookies arent being set in my first view.
Is this how it should be ? or am I mistaken
Please view the code below for further illustration:
if( !get_cookie('rate') ){
$cookie_rate = array(
'name' => 'rate',
'value' => '10',
'expire' => '100000'
);
set_cookie($cookie_rate);
}
var_dump( get_cookie('rate') ); //returns ( boolean false )
if( !isset($_COOKIE['foo']) ){
$_COOKIE['foo'] = 'bar';
}
var_dump( $_COOKIE['foo'] ); // This yields string 'bar' (length=3) on the first visit
Doing the same thing with php cookies yeilds an array with cookie values.
This problem persists only in the first visit of a page.
This isn't a CodeIgniter vs PHP issue. You just don't understand how cookies work.
Cookies are a header sent by the server which the browser must send back on subsequent requests. $this->input->set_cookie() and set_cookie() send a cookie header.
$_COOKIES on PHP (and thus $this->input->cookie() and therefore the get_cookie() helper) only contain cookies which the browser sent.
Thus when you set a cookie with set_cookie(), you won't be able to get_cookie() until the browser's next request.
Seeing as CI's set_cookie probably utilizes the same mechanism as PHP's setcookie(), this entry from the manual probably applies:
Common pitfalls
Cookies will not become visible until the next loading of a page that the cookie should be visible for. To test if a cookie was successfully set, check for the cookie on a next loading page before the cookie expires. Expire time is set via the expire parameter. A nice way to debug the existence of cookies is by simply calling print_r($_COOKIE);.
I can't see any mention of this behaviour in the CI manual, but it's likely to be the same thing.
If I understood this right youre trying to see the data of the cookie before reloading the page which won't work. Try setting the cookie, reloading the page and then checking the cookie for data.
Also sometimes you need to specify domain and such, perhaps it doesn't apply right now but it might be nice to know later if they suddenly stop working, from CI-documentation:
$cookie = array(
'name' => 'The Cookie Name',
'value' => 'The Value',
'expire' => '86500',
'domain' => '.some-domain.com',
'path' => '/',
'prefix' => 'myprefix_',
'secure' => TRUE
);
$this->input->set_cookie($cookie);
Also, consider using the session class instead of cookies if you don't need anything specifically from cookies since they are more secure. http://codeigniter.com/user_guide/libraries/sessions.html
Thats probably not the problem, in fact thats how cookie works, its set and on next page load it seems to be visible from then.