1
votes

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.

2

2 Answers

1
votes

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.

0
votes

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

<a href="https://www.example.com/test1.php">go to test</a>

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.