Merge pull request #850 from RS71/develop

CSRF optional token regeneration
diff --git a/application/config/config.php b/application/config/config.php
index bb35324..17b854b 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -326,12 +326,14 @@
 | 'csrf_token_name' = The token name
 | 'csrf_cookie_name' = The cookie name
 | 'csrf_expire' = The number in seconds the token should expire.
+| 'csrf_regenerate' = Regenerate token on every submission
 | 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks
 */
 $config['csrf_protection'] = FALSE;
 $config['csrf_token_name'] = 'csrf_test_name';
 $config['csrf_cookie_name'] = 'csrf_cookie_name';
 $config['csrf_expire'] = 7200;
+$config['csrf_regenerate'] = TRUE;
 $config['csrf_exclude_uris'] = array();
 
 /*
diff --git a/system/core/Security.php b/system/core/Security.php
index 272a8bf..f7998da 100755
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -180,9 +180,14 @@
 		// polute the _POST array
 		unset($_POST[$this->_csrf_token_name]);
 
-		// Nothing should last forever
-		unset($_COOKIE[$this->_csrf_cookie_name]);
-		$this->_csrf_hash = '';
+		// Regenerate on every submission?
+		if (config_item('csrf_regenerate'))
+		{
+			// Nothing should last forever
+			unset($_COOKIE[$this->_csrf_cookie_name]);
+			$this->_csrf_hash = '';
+		}
+		
 		$this->_csrf_set_hash();
 		$this->csrf_set_cookie();
 
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 7e7be06..d9eca7f 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -65,6 +65,8 @@
 	    if they are set manually after initialization.
    -  Minor speed optimizations and method & property visibility declarations in the Calendar Library.
    -  Removed SHA1 function in the :doc:`Encryption Library <libraries/encryption>`.
+   -  Added $config['csrf_regeneration'] to the CSRF protection in the :doc:`Security library <libraries/security>`, which makes token regeneration optional.
+
 
 -  Core
 
diff --git a/user_guide_src/source/libraries/security.rst b/user_guide_src/source/libraries/security.rst
index 8ee0c6e..e7d2555 100644
--- a/user_guide_src/source/libraries/security.rst
+++ b/user_guide_src/source/libraries/security.rst
@@ -85,6 +85,10 @@
 form_open() function will automatically insert a hidden csrf field in
 your forms.
 
+Tokens may be either regenerated on every submission (default) or kept the same throughout the life of the CSRF cookie. The default regeneration of tokens provides stricter security but may result in usability concerns as other tokens become invalid (back/forward navigation, multiple tabs/windows, asynchronous actions, etc). You may alter this behavior by editing the following config parameter::
+
+	$config['csrf_regeneration'] = TRUE;
+
 Select URIs can be whitelisted from csrf protection (for example API
 endpoints expecting externally POSTed content). You can add these URIs
 by editing the 'csrf_exclude_uris' config parameter::