Skip to content

Commit 756129f

Browse files
authored
Merge pull request #89 from mebjas/dev-master
path, domain and secure parameters of setcookie method made configurable
2 parents 98459c2 + 8e1d6f7 commit 756129f

File tree

6 files changed

+119
-13
lines changed

6 files changed

+119
-13
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,4 @@ after_success:
4545
cache:
4646
directories:
4747
- vendor
48-
- $HOME/.cache/composer
48+
- $HOME/.cache/composer

libs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ CSRFProtector configuration
1515
- `customErrorMessage`: **Error Message** to be shown to user. Only this text will be shown!<br>**Default: null**
1616
- `jsUrl`: **Absolute url** of the js file. (See [Setting up](https://github.com/mebjas/CSRF-Protector-PHP/wiki/Setting-up-CSRF-Protector-PHP-in-your-web-application) for more information)
1717
- `tokenLength`: length of csrfp token, Default `10`
18-
- `secureCookie`: sets the "secure" HTTPS flag on the cookie. <br>**Default: `false`**
18+
- `cookieConfig`: Array of parameter values for set cookie method. supports three properties: `path`, `domain`, `secure`. They have same meaning as respective parameters of `setcookie` method: [learn more - php.net]
1919
- `disabledJavascriptMessage`: messaged to be shown if js is disabled (string)
2020
- `verifyGetFor`: regex rules for those urls for which csrfp validation should be enabled for `GET` requests also. (View [verifyGetFor rules](https://github.com/mebjas/CSRF-Protector-PHP/wiki/verifyGetFor-rules) for more information)

libs/config.sample.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717
"customErrorMessage" => "",
1818
"jsUrl" => "",
1919
"tokenLength" => 10,
20-
"secureCookie" => false,
20+
"cookieConfig" => array(
21+
"path" => '',
22+
"domain" => '',
23+
"secure" => false
24+
),
2125
"disabledJavascriptMessage" => "This site attempts to protect users against <a href=\"https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29\">
2226
Cross-Site Request Forgeries </a> attacks. In order to do so, you must have JavaScript enabled in your web browser otherwise this site will fail to work correctly for you.
2327
See details of your web browser for how to enable JavaScript.",

libs/csrf/csrfprotector.php

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,47 @@ class baseJSFileNotFoundExceptio extends \exception {};
2323
class incompleteConfigurationException extends \exception {};
2424
class alreadyInitializedException extends \exception {};
2525

26+
/**
27+
* Cookie config class
28+
*/
29+
class cookieConfig
30+
{
31+
/**
32+
* Variable: $path
33+
* path parameter for setcookie method
34+
* @var string
35+
*/
36+
public $path = '';
37+
38+
/**
39+
* Variable: $domain
40+
* domain parameter for setcookie method
41+
* @var string
42+
*/
43+
public $domain = '';
44+
45+
/**
46+
* Variable: $secure
47+
* secure parameter for setcookie method
48+
* @var bool
49+
*/
50+
public $secure = false;
51+
52+
/**
53+
* Function: constructor
54+
*
55+
* Parameters:
56+
* $cfg - config array loaded from config file;
57+
*/
58+
function __construct($cfg) {
59+
if ($cfg !== null) {
60+
if (isset($cfg['path'])) $this->path = $cfg['path'];
61+
if (isset($cfg['domain'])) $this->domain = $cfg['domain'];
62+
if (isset($cfg['secure'])) $this->secure = (bool) $cfg['secure'];
63+
}
64+
}
65+
}
66+
2667
class csrfProtector
2768
{
2869
/*
@@ -46,6 +87,13 @@ class csrfProtector
4687
*/
4788
private static $isValidHTML = false;
4889

90+
/**
91+
* Variable: $cookieConfig
92+
* Array of parameters for the setcookie method
93+
* @var cookieConfig;
94+
*/
95+
private static $cookieConfig = null;
96+
4997
/*
5098
* Variable: $requestType
5199
* Varaible to store weather request type is post or get
@@ -140,6 +188,11 @@ public static function init($length = null, $action = null)
140188
if (self::$config['CSRFP_TOKEN'] == '')
141189
self::$config['CSRFP_TOKEN'] = CSRFP_TOKEN;
142190

191+
// load parameters for setcookie method
192+
if (!isset(self::$config['cookieConfig']))
193+
self::$config['cookieConfig'] = array();
194+
self::$cookieConfig = new cookieConfig(self::$config['cookieConfig']);
195+
143196
// Validate the config if everythings filled out
144197
// TODO: collect all missing values and throw exception together
145198
foreach (self::$requiredConfigurations as $value) {
@@ -328,16 +381,23 @@ public static function refreshToken()
328381
|| !is_array($_SESSION[self::$config['CSRFP_TOKEN']]))
329382
$_SESSION[self::$config['CSRFP_TOKEN']] = array();
330383

331-
//set token to session for server side validation
384+
// set token to session for server side validation
332385
array_push($_SESSION[self::$config['CSRFP_TOKEN']], $token);
333386

334-
//set token to cookie for client side processing
335-
setcookie(self::$config['CSRFP_TOKEN'],
387+
// set token to cookie for client side processing
388+
if (self::$cookieConfig === null) {
389+
if (!isset(self::$config['cookieConfig']))
390+
self::$config['cookieConfig'] = array();
391+
self::$cookieConfig = new cookieConfig(self::$config['cookieConfig']);
392+
}
393+
394+
setcookie(
395+
self::$config['CSRFP_TOKEN'],
336396
$token,
337397
time() + self::$cookieExpiryTime,
338-
'',
339-
'',
340-
(array_key_exists('secureCookie', self::$config) ? (bool)self::$config['secureCookie'] : false));
398+
self::$cookieConfig->path,
399+
self::$cookieConfig->domain,
400+
(bool) self::$cookieConfig->secure);
341401
}
342402

343403
/*

test/config.test.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@
1717
"customErrorMessage" => "",
1818
"jsUrl" => "http://localhost/csrfp/js/csrfprotector.js",
1919
"tokenLength" => 10,
20-
"secureCookie" => false,
20+
"cookieConfig" => array(
21+
"path" => '',
22+
"domain" => '',
23+
"secure" => false
24+
),
2125
"disabledJavascriptMessage" => "This site attempts to protect users against <a href=\"https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29\">
2226
Cross-Site Request Forgeries </a> attacks. In order to do so, you must have JavaScript enabled in your web browser otherwise this site will fail to work correctly for you.
2327
See details of your web browser for how to enable JavaScript.",

test/csrfprotector_test.php

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public function setUp()
9191
$this->logDir = __DIR__ .'/logs';
9292

9393
csrfprotector::$config['CSRFP_TOKEN'] = 'csrfp_token';
94-
csrfprotector::$config['secureCookie'] = false;
94+
csrfprotector::$config['cookieConfig'] = array('secure' => false);
9595
csrfprotector::$config['logDirectory'] = '../test/logs';
9696

9797
$_SERVER['REQUEST_URI'] = 'temp'; // For logging
@@ -142,6 +142,35 @@ public function testRefreshToken()
142142
$this->assertTrue(csrfp_wrapper::checkHeader($_SESSION[csrfprotector::$config['CSRFP_TOKEN']][1]));
143143
}
144144

145+
/**
146+
* Function to check cookieconfig class
147+
*/
148+
public function testCookieConfigClass() {
149+
$cfg = array(
150+
"path" => "abcd",
151+
"secure" => true,
152+
"domain" => "abcd",
153+
);
154+
155+
// simple test
156+
$cookieConfig = new cookieConfig($cfg);
157+
$this->assertEquals($cookieConfig->path, "abcd");
158+
$this->assertEquals($cookieConfig->domain, "abcd");
159+
$this->assertEquals($cookieConfig->secure, true);
160+
161+
// default value test
162+
$cookieConfig = new cookieConfig(array());
163+
$this->assertEquals($cookieConfig->path, '');
164+
$this->assertEquals($cookieConfig->domain, '');
165+
$this->assertEquals($cookieConfig->secure, false);
166+
167+
// secure as string
168+
$cookieConfig = new cookieConfig(array('secure' => 'true'));
169+
$this->assertEquals($cookieConfig->secure, true);
170+
$cookieConfig = new cookieConfig(array('secure' => 'false'));
171+
$this->assertEquals($cookieConfig->secure, true);
172+
}
173+
145174
/**
146175
* test secure flag is set in the token cookie when requested
147176
*/
@@ -150,11 +179,20 @@ public function testSecureCookie()
150179
$_SERVER['REQUEST_METHOD'] = 'POST';
151180
$_SESSION[csrfprotector::$config['CSRFP_TOKEN']] = array('123abcd');
152181

153-
csrfprotector::$config['secureCookie'] = false;
182+
// this one would generally fails, as init was already called and now private static
183+
// property is set with secure as false;
184+
$csrfp = new csrfProtector;
185+
$reflection = new \ReflectionClass(get_class($csrfp));
186+
$property = $reflection->getProperty('cookieConfig');
187+
$property->setAccessible(true);
188+
189+
// change value to false
190+
$property->setValue($csrfp, new cookieConfig(array('secure' => false)));
154191
csrfprotector::refreshToken();
155192
$this->assertNotRegExp('/; secure/', csrfp_wrapper::getHeaderValue('Set-Cookie'));
156193

157-
csrfprotector::$config['secureCookie'] = true;
194+
// change value to true
195+
$property->setValue($csrfp, new cookieConfig(array('secure' => true)));
158196
csrfprotector::refreshToken();
159197
$this->assertRegExp('/; secure/', csrfp_wrapper::getHeaderValue('Set-Cookie'));
160198
}

0 commit comments

Comments
 (0)