PHP setting a Session-Cookie with samesite - php

I currently have a PHP script that sets the sametime cookie as follows:
session_set_cookie_params($cookie_timeout, $cookieParams["path"], $cookie_domain, $session_secure, $cookie_httponly);
I want to add samesite="Lax" to the above statement by adding an extra parameter where ($cookie_samesite="Lax")
session_set_cookie_params($cookie_timeout, $cookieParams["path"], $cookie_domain, $session_secure, $cookie_httponly, $cookie_samesite);
The new output of the statement would look like
1800, /, ".vasports.com.au", 1, 1, "Lax"
Is this the correct format for the samesite parameter?
NOTE: I do not have a PHP7.3 installed yet. Hence I can't test this properly.
And I've referred to PHP doco for "session_set_cookie_params".
I have also checked
PHP setcookie "SameSite=Strict"?

As of PHP 7.3 you can throw an options array into set_cookie_params that supports SameSite.
session_set_cookie_params([
'lifetime' => $cookie_timeout,
'path' => '/',
'domain' => $cookie_domain,
'secure' => $session_secure,
'httponly' => $cookie_httponly,
'samesite' => 'Lax'
]);
On PHP <7.3 you can add the SameSite parameter adding it in the "path" param.
session_set_cookie_params([
'lifetime' => $cookie_timeout,
'path' => '/;SameSite=none', // <-- this way!
'domain' => $cookie_domain,
'secure' => $session_secure,
'httponly' => $cookie_httponly,
'samesite' => 'Lax'
]);

Adapted from SilverShadow answer, but fixing the syntax for php <7.3,
since session_set_cookie_params() can't take an array as single parameter until preciselly 7.3, instead each parameter needs to be set.
and autodetecting php version for the correct option so you can use it even if you later upgrade to 7.3:
// set as your own needs:
$maxlifetime = 0;
$path = '/';
$domain = '';
$secure = false;
$httponly = false;
$samesite = 'lax'; // here is what we need
if(PHP_VERSION_ID < 70300) {
session_set_cookie_params($maxlifetime, $path.'; samesite='.$samesite, $domain, $secure, $httponly);
} else {
// note I use `array()` instead of `[]` to allow support of php <5.4
session_set_cookie_params(array(
'lifetime' => $maxlifetime,
'path' => $path,
'domain' => $domain,
'secure' => $secure,
'httponly' => $httponly,
'samesite' => $samesite
));
}

After some further research ...
Get current parameters first.
Then change the parameters as required, in this case [samesite]="Lax".
Set the cookie.
$cookieParams = session_get_cookie_params();
$cookieParams[samesite] = "Lax";
session_set_cookie_params($cookieParams);
Check your 'set-cookie:' header and you should now see the text 'SameSite=Lax' at the end like this.
set-cookie: ssid=b930bc608a911781f459a4f46b2c513d; expires=Wed, 16-Oct-2019 10:48:49 GMT; Max-Age=1800; path=/; secure; HttpOnly; SameSite=Lax

Related

PHP setcookie function including samesite parameter does not work

I have a fully working setcookie() php function running using these params...
<?php
setcookie(
'_siteauth',
Crypt::encrypt(site()->password),
time() + 86400,
'/',
);
?>
The code above sets a cookie everytime with no issues!
But as soon as I attempt to use samesite option the cookie never sets... which is a problem.
I am not running this in a iFrame. I am testing this locally using dockers wordpress image, which I cant see being a problem.
At first after all the online reading, I thought it might be a PHP version conflict, but it failed to work in either tests pre/post PHP version 7.3.0.
After reading https://www.php.net/manual/en/function.setcookie.php
...it says options can be set as associative array including expires, path, domain, secure, httponly and samesite, but everytime I try this php setcookie method it does not set.
This is my locally dumped $_SERVER['HTTP_HOST'] result...
demo.local.mydomain.com
Here are all my local tested code attempts, using $_SERVER['HTTP_HOST'] for domain...
<?php
setcookie(
'_siteauth',
Crypt::encrypt(site()->password),
[
'expires' => time() + 86400,
'path' => '/',
'domain' => $_SERVER['HTTP_HOST'],
'samesite' => 'None',
'secure' => false,
'httponly' => false
]
);
?>
<?php
setcookie(
'_siteauth',
Crypt::encrypt(site()->password),
time() + 86400,
'/; SameSite=none'
);
?>
<?php
setcookie(
'_siteauth',
Crypt::encrypt(site()->password),
[
'expires' => time() + 86400,
'path' => '/',
'domain' => $_SERVER['HTTP_HOST'],
'secure' => false,
'httponly' => false,
'samesite' => 'None'
]
);
?>
And none of these code examples save the _siteauth cookie when executed.
I've tried every variation of php version setcookie() including the samesite key and value but no cookie is saved.
The reason I am changing my previous setcookie() script is because there was a change early in 2020 in chrome with iframe cookie policies, defaulting to samesite Lax. So I need to force samesite None when setting my cookie.
https://web.dev/samesite-cookies-explained/
https://web.dev/samesite-cookie-recipes/
If anyone can see where I'm going wrong, help would be amazing.
When you set a cookie with SameSite=None it'll be blocked (by the browser) unless it also has Secure, which is omitted/set to false in the code snippets.
setcookie(
'_siteauth',
Crypt::encrypt(site()->password),
[
'expires' => time() + 86400,
'path' => '/',
'domain' => $_SERVER['HTTP_HOST'],
'samesite' => 'None',
'secure' => true,
]
);

Set cookie for subdomain

I have some domain example.com. User logs in from the example.com and I want to set cookies for subdomains foo.example.com, bar.example.com etc.
When I try to set it like such:
setcookie($cookie_name, $token, $expires, '/', '.example.com');
I got an error
"Set-Cookie was blocked because its Domain attribute was invalid with regards to the current host url" in my Chrome 92.
When I try to make it with samesite=none:
setcookie($cookie_name, $token, [
'expires' => $expires,
'path' => '/',
'domain' => '.example.com',
'secure' => true,
'httponly' => true,
'samesite' => 'None'
]);
I have the same error in my Chrome 92.
I didn't test it with https yet.
Is it possible to set cookie for subdomain for HTTP?

session lost after redirect header location in safari and edge (only from webmail)

I send a hyperlink inside a mail, the target is like https://example.com/category/12345/ch3k5um/.
The .htaccess navigate the request to index?cat=category&id=12345&checksum=ch3k5um
If everything is ok, session will be set
$_SESSION = array( 'foo' => 'bar' );
And an then redirect to the target
header ('location: /target/page', true, 302);
In there is the check isset($_SESSION['foo']).
This works fine from different mail-clients like thunderbird or apple-mail with all browsers. And also from normal login-form.
If i click this link in a webmail like "web.de" or "gmx.net", it goes to their dereferrer, than to the called link,
there the session will be set - and redirect to /target/page -
and here the session is lost, but only with safari and edge..
After some hours struggeling i found the solution.
The Problem of losing the session after redirect with header location,
The new "samesite" attribute from PHP 7.3.
If this is Strict, you will lose the session after header( 'Location: /foo' , true, 302);
use Lax and fine..
At this moment i dont know why this just happens from webmail and only on safari and edge..
the session_starts at the top of the scripts:
$sessionSet = array(
'path' => '/',
'domain' => $_SERVER[ 'HTTP_HOST' ],
'secure' => TRUE,
'httponly' => TRUE,
'samesite' => 'Lax', // Strict will lose the session for some reason in some case..
'lifetime' => 18000
);
ini_set( 'session.save_path', '/dir/to/sessions' );
ini_set( 'session.cookie_lifetime', $sessionSet[ 'lifetime' ] );
ini_set( 'session.gc_maxlifetime', $sessionSet[ 'lifetime' ] );
ini_set( 'session.gc_probability', 1 );
ini_set( 'session.gc_divisor', 3 );
ini_set( 'session.cookie_samesite', $sessionSet[ 'samesite' ] );
session_set_cookie_params( $sessionSet );
session_start();

Is there any way to overwrite CONSUMER_KEY and CONSUMER_SECRET

I am using laravel with the thujohn/twitter package.
But i want whenever any use registered they will provide us CONSUMER_KEY and CONSUMER_SECRET and we will use that details to post the tweet,favorites tweet etc.
But in the thujohn/twitter package the CONSUMER_KEY and CONSUMER_SECRET is set one time and that will use for all users and i want to use each register user will use their own consumer details.
Any one know any solution on the same
Looking at the source code you have the reconfigure method:
/**
* Set new config values for the OAuth class like different tokens.
*
* #param Array $config An array containing the values that should be overwritten.
*
* #return void
*/
public function reconfig($config)
{
// The consumer key and secret must always be included when reconfiguring
$config = array_merge($this->parent_config, $config);
parent::reconfigure($config);
return $this;
}
So you can pass an array with the configs you want:
Twitter::reconfigure([
'consumer_key' => '',
'consumer_secret' => '',
'token' => '',
'secret' => '',
]);
This configs will then be passed to the parent which is another library called tmhOAuth here's the code for that:
public function reconfigure($config=array()) {
// default configuration options
$this->config = array_merge(
array(
// leave 'user_agent' blank for default, otherwise set this to
// something that clearly identifies your app
'user_agent' => '',
'host' => 'api.twitter.com',
'method' => 'GET',
'consumer_key' => '',
'consumer_secret' => '',
'token' => '',
'secret' => '',
// OAuth2 bearer token. This should already be URL encoded
'bearer' => '',
// oauth signing variables that are not dynamic
'oauth_version' => '1.0',
'oauth_signature_method' => 'HMAC-SHA1',
// you probably don't want to change any of these curl values
'curl_http_version' => CURL_HTTP_VERSION_1_1,
'curl_connecttimeout' => 30,
'curl_timeout' => 10,
// for security this should always be set to 2.
'curl_ssl_verifyhost' => 2,
// for security this should always be set to true.
'curl_ssl_verifypeer' => true,
// for security this should always be set to true.
'use_ssl' => true,
// you can get the latest cacert.pem from here http://curl.haxx.se/ca/cacert.pem
// if you're getting HTTP 0 responses, check cacert.pem exists and is readable
// without it curl won't be able to create an SSL connection
'curl_cainfo' => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem',
'curl_capath' => __DIR__,
// in some cases (very very odd ones) the SSL version must be set manually.
// unless you know why your are changing this, you should leave it as false
// to allow PHP to determine the value for this setting itself.
'curl_sslversion' => false,
'curl_followlocation' => false, // whether to follow redirects or not
// support for proxy servers
'curl_proxy' => false, // really you don't want to use this if you are using streaming
'curl_proxyuserpwd' => false, // format username:password for proxy, if required
'curl_encoding' => '', // leave blank for all supported formats, else use gzip, deflate, identity etc
// streaming API configuration
'is_streaming' => false,
'streaming_eol' => "\r\n",
'streaming_metrics_interval' => 10,
// header or querystring. You should always use header!
// this is just to help me debug other developers implementations
'as_header' => true,
'force_nonce' => false, // used for checking signatures. leave as false for auto
'force_timestamp' => false, // used for checking signatures. leave as false for auto
),
$config
);
}

Codeigniter unable to read cookie

I can set the cookie like this:
$cookie = array(
'name' => 'token',
'value' => $some_value,
'expire' => '86500',
'domain' => '192.168.1.11',
'path' => '/appfolder',
'prefix' => '',
'secure' => TRUE
);
$this->input->set_cookie($cookie);
it's there (I can see in Firefox settings).
But i can't read it. This is the code in my controller:
$this->load->helper('cookie');
$token = get_cookie('token', false); //Same if TRUE
//$this->input->cookie('cookie_name', TRUE); //also does not work
var_dump($token);
var_dump outputs bool(false).
First check your config.php cookie settings.If they are set wrong, cookies won't work
On the other hand, CI built in function has some problem which writes the cookie. you can change it by this way:
use setcookie function to set cookie setcookie($name,$value,$expire,$path);
and getting it back through $this->input->cookie('user',TRUE);
Have a look here http://ellislab.com/codeigniter/user-guide/libraries/input.html
setcookie ( 'token' , $some_value , 86500, '/appfolder' , '192.168.1.11', FALSE );

Categories