PHP setcookie function including samesite parameter does not work - php

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,
]
);

Related

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();

PHP setting a Session-Cookie with samesite

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

OAuth2 PHP change expiration time

I use this library : Oauth2 PHP
I can't find the setting to change the expiration time, I tried:
new OAuth2\Server($this->_mem, array('use_jwt_access_tokens' => true, 'access_token_lifetime' => 2419200));
But the lifetime of the token is always 3600. What's the right setting?
Edit: As suggested, I tried to use refresh token
new OAuth2\Server($this->_mem, array('use_jwt_access_tokens' => true, 'always_issue_new_refresh_token' => true));
The client_credential grant type + JWT bearer works but I never get a refresh token (only access token). Even upon token verification, I never get a refresh token.
Edit: Since the refresh doesn't work for me, as suggested I tried to set the token expiration time doing
new OAuth2\Server($this->_mem, array('use_jwt_access_tokens' => true, 'access_lifetime' => 12000));
The response upon client credential still returns a short token
{ ["access_token"]=> string(648) "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpZCI6ImU0NjE0MzdhMjY2YjFkNWY0OWU5MDY5MjQwODg5NjU0MDI2ZGRmODAiLCJpc3MiOiIiLCJhdWQiOiI4OWM2MjRmNTNiYTVmOTM3NjFmZWFhNmU1MGI1ZDk1NGQ4ZGRjMTIxIiwic3ViIjpudWxsLCJleHAiOjE0MzQ0NjI2NDIsImlhdCI6MTQzNDQ1OTA0MiwidG9rZW5fdHlwZSI6ImJlYXJlciIsInNjb3BlIjoicHVibGljIHJlYWRfbmV3cyJ9.Mk_KyUk_8yPnq9eEjvgVOJXBOkQSifAPbEaUvY4X9WvfmImPnC7PJx_99ODpiJR_gMLhZ3gBl1gQEJ2z6xUZ83dntCYzGWumkVLNpJG8omuVkmZqNnbLYYXl-vzmGOblceeDrKw_lrXc4rb72BeFaMeZWwFV7YMrgA0LOsYyZmAiDblcbHtpPGpUd2EC3y7VxLnyA8u07eY4aswOHwClPlDwHX_HwfMUmDLWkoTcrRf1AvKn-cnj41eL0SU9AJHWab8AOK7lxDsaqnits5pXj--cG9hr8pWOsFPQ2D9qYOsMvbEOi4zDJEdaIp-qvzn6N5Wrm5GxdbU1AqwvM531hQ" ["expires_in"]=> int(3600) ["token_type"]=> string(6) "bearer" ["scope"]=> string(16) "public" }
It appears it was a cache issue, the token is now set to the proper expiration length/time
You can change the access_token lifetime using the access_lifetime OAuth2\Server config parameter from examining the code.
The access_lifetime config parameter is used in creating the token in OAuth2\ResponseType\JwtAccessToken line 63:
$expires = time() + $this->config['access_lifetime'];
This can be set when instantiating the server which takes the following config parameters as listed in OAuth2\Server lines 109 - 126.
// merge all config values. These get passed to our controller objects
$this->config = array_merge(array(
'use_jwt_access_tokens' => false,
'store_encrypted_token_string' => true,
'use_openid_connect' => false,
'id_lifetime' => 3600,
'access_lifetime' => 3600,
'www_realm' => 'Service',
'token_param_name' => 'access_token',
'token_bearer_header_name' => 'Bearer',
'enforce_state' => true,
'require_exact_redirect_uri' => true,
'allow_implicit' => false,
'allow_credentials_in_request_body' => true,
'allow_public_clients' => true,
'always_issue_new_refresh_token' => false,
'unset_refresh_token_after_use' => true,
), $config);
There is also support for refresh tokens according to the code for Server.php and JwtAccessToken.php.
In server.php (where you are passing grant type and client credentials)
$config = array(
'access_lifetime' => 86400
);
$server = new OAuth2\Server($storage, $config);
source: https://github.com/bshaffer/oauth2-server-php/issues/699

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