Move token generation to Security namespace
This commit is contained in:
parent
06e9486c59
commit
6756ef2301
|
|
@ -5,7 +5,7 @@ namespace Kanboard\Auth;
|
|||
use Kanboard\Core\Base;
|
||||
use Kanboard\Core\Request;
|
||||
use Kanboard\Event\AuthEvent;
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Security\Token;
|
||||
|
||||
/**
|
||||
* RememberMe model
|
||||
|
|
@ -165,8 +165,8 @@ class RememberMe extends Base
|
|||
*/
|
||||
public function create($user_id, $ip, $user_agent)
|
||||
{
|
||||
$token = hash('sha256', $user_id.$user_agent.$ip.Security::generateToken());
|
||||
$sequence = Security::generateToken();
|
||||
$token = hash('sha256', $user_id.$user_agent.$ip.Token::getToken());
|
||||
$sequence = Token::getToken();
|
||||
$expiration = time() + self::EXPIRATION;
|
||||
|
||||
$this->cleanup($user_id);
|
||||
|
|
@ -216,7 +216,7 @@ class RememberMe extends Base
|
|||
*/
|
||||
public function update($token)
|
||||
{
|
||||
$new_sequence = Security::generateToken();
|
||||
$new_sequence = Token::getToken();
|
||||
|
||||
$this->db
|
||||
->table(self::TABLE)
|
||||
|
|
|
|||
|
|
@ -3,9 +3,6 @@
|
|||
namespace Kanboard\Controller;
|
||||
|
||||
use Pimple\Container;
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Request;
|
||||
use Kanboard\Core\Response;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
|
|
@ -16,22 +13,6 @@ use Symfony\Component\EventDispatcher\Event;
|
|||
*/
|
||||
abstract class Base extends \Kanboard\Core\Base
|
||||
{
|
||||
/**
|
||||
* Request instance
|
||||
*
|
||||
* @accesss protected
|
||||
* @var \Kanboard\Core\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* Response instance
|
||||
*
|
||||
* @accesss protected
|
||||
* @var \Kanboard\Core\Response
|
||||
*/
|
||||
protected $response;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
|
@ -41,11 +22,9 @@ abstract class Base extends \Kanboard\Core\Base
|
|||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->request = new Request;
|
||||
$this->response = new Response;
|
||||
|
||||
if (DEBUG) {
|
||||
$this->container['logger']->debug('START_REQUEST='.$_SERVER['REQUEST_URI']);
|
||||
$this->logger->debug('START_REQUEST='.$_SERVER['REQUEST_URI']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,14 +36,14 @@ abstract class Base extends \Kanboard\Core\Base
|
|||
public function __destruct()
|
||||
{
|
||||
if (DEBUG) {
|
||||
foreach ($this->container['db']->getLogMessages() as $message) {
|
||||
$this->container['logger']->debug($message);
|
||||
foreach ($this->db->getLogMessages() as $message) {
|
||||
$this->logger->debug($message);
|
||||
}
|
||||
|
||||
$this->container['logger']->debug('SQL_QUERIES={nb}', array('nb' => $this->container['db']->nbQueries));
|
||||
$this->container['logger']->debug('RENDERING={time}', array('time' => microtime(true) - @$_SERVER['REQUEST_TIME_FLOAT']));
|
||||
$this->container['logger']->debug('MEMORY='.$this->helper->text->bytes(memory_get_usage()));
|
||||
$this->container['logger']->debug('END_REQUEST='.$_SERVER['REQUEST_URI']);
|
||||
$this->logger->debug('SQL_QUERIES={nb}', array('nb' => $this->container['db']->nbQueries));
|
||||
$this->logger->debug('RENDERING={time}', array('time' => microtime(true) - @$_SERVER['REQUEST_TIME_FLOAT']));
|
||||
$this->logger->debug('MEMORY='.$this->helper->text->bytes(memory_get_usage()));
|
||||
$this->logger->debug('END_REQUEST='.$_SERVER['REQUEST_URI']);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -201,7 +180,7 @@ abstract class Base extends \Kanboard\Core\Base
|
|||
*/
|
||||
protected function checkCSRFParam()
|
||||
{
|
||||
if (! Security::validateCSRFToken($this->request->getStringParam('csrf_token'))) {
|
||||
if (! $this->token->validateCSRFToken($this->request->getStringParam('csrf_token'))) {
|
||||
$this->forbidden();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Core;
|
|||
* @package core
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Request
|
||||
class Request extends Base
|
||||
{
|
||||
/**
|
||||
* Get URL string parameter
|
||||
|
|
@ -57,7 +57,8 @@ class Request
|
|||
*/
|
||||
public function getValues()
|
||||
{
|
||||
if (! empty($_POST) && Security::validateCSRFFormToken($_POST)) {
|
||||
if (! empty($_POST) && ! empty($_POST['csrf_token']) && $this->token->validateCSRFToken($_POST['csrf_token'])) {
|
||||
unset($_POST['csrf_token']);
|
||||
return $_POST;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Kanboard\Core;
|
|||
* @package core
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Response
|
||||
class Response extends Base
|
||||
{
|
||||
/**
|
||||
* Send no cache headers
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Kanboard\Core;
|
||||
namespace Kanboard\Core\Security;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
|
||||
/**
|
||||
* Security class
|
||||
* Token Handler
|
||||
*
|
||||
* @package core
|
||||
* @package security
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Security
|
||||
class Token extends Base
|
||||
{
|
||||
/**
|
||||
* Generate a random token with different methods: openssl or /dev/urandom or fallback to uniqid()
|
||||
|
|
@ -17,7 +19,7 @@ class Security
|
|||
* @access public
|
||||
* @return string Random token
|
||||
*/
|
||||
public static function generateToken()
|
||||
public static function getToken()
|
||||
{
|
||||
if (function_exists('openssl_random_pseudo_bytes')) {
|
||||
return bin2hex(\openssl_random_pseudo_bytes(30));
|
||||
|
|
@ -31,18 +33,16 @@ class Security
|
|||
/**
|
||||
* Generate and store a CSRF token in the current session
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @return string Random token
|
||||
*/
|
||||
public static function getCSRFToken()
|
||||
public function getCSRFToken()
|
||||
{
|
||||
$nonce = self::generateToken();
|
||||
|
||||
if (empty($_SESSION['csrf_tokens'])) {
|
||||
if (! isset($_SESSION['csrf_tokens'])) {
|
||||
$_SESSION['csrf_tokens'] = array();
|
||||
}
|
||||
|
||||
$nonce = self::getToken();
|
||||
$_SESSION['csrf_tokens'][$nonce] = true;
|
||||
|
||||
return $nonce;
|
||||
|
|
@ -51,12 +51,11 @@ class Security
|
|||
/**
|
||||
* Check if the token exists for the current session (a token can be used only one time)
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param string $token CSRF token
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateCSRFToken($token)
|
||||
public function validateCSRFToken($token)
|
||||
{
|
||||
if (isset($_SESSION['csrf_tokens'][$token])) {
|
||||
unset($_SESSION['csrf_tokens'][$token]);
|
||||
|
|
@ -65,22 +64,4 @@ class Security
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the token used in a form is correct and then remove the value
|
||||
*
|
||||
* @static
|
||||
* @access public
|
||||
* @param array $values Form values
|
||||
* @return bool
|
||||
*/
|
||||
public static function validateCSRFFormToken(array &$values)
|
||||
{
|
||||
if (! empty($values['csrf_token']) && self::validateCSRFToken($values['csrf_token'])) {
|
||||
unset($values['csrf_token']);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Kanboard\Helper;
|
||||
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Base;
|
||||
|
||||
/**
|
||||
* Form helpers
|
||||
|
|
@ -10,7 +10,7 @@ use Kanboard\Core\Security;
|
|||
* @package helper
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Form extends \Kanboard\Core\Base
|
||||
class Form extends Base
|
||||
{
|
||||
/**
|
||||
* Hidden CSRF token field
|
||||
|
|
@ -20,7 +20,7 @@ class Form extends \Kanboard\Core\Base
|
|||
*/
|
||||
public function csrf()
|
||||
{
|
||||
return '<input type="hidden" name="csrf_token" value="'.Security::getCSRFToken().'"/>';
|
||||
return '<input type="hidden" name="csrf_token" value="'.$this->token->getCSRFToken().'"/>';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace Kanboard\Helper;
|
||||
|
||||
use Kanboard\Core\Request;
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Base;
|
||||
|
||||
/**
|
||||
* Url helpers
|
||||
|
|
@ -11,7 +11,7 @@ use Kanboard\Core\Security;
|
|||
* @package helper
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Url extends \Kanboard\Core\Base
|
||||
class Url extends Base
|
||||
{
|
||||
private $base = '';
|
||||
private $directory = '';
|
||||
|
|
@ -158,7 +158,7 @@ class Url extends \Kanboard\Core\Base
|
|||
}
|
||||
|
||||
if ($csrf) {
|
||||
$qs['csrf_token'] = Security::getCSRFToken();
|
||||
$qs['csrf_token'] = $this->token->getCSRFToken();
|
||||
}
|
||||
|
||||
if (! empty($qs)) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace Kanboard\Model;
|
||||
|
||||
use Kanboard\Core\Translator;
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Security\Token;
|
||||
use Kanboard\Core\Session;
|
||||
|
||||
/**
|
||||
|
|
@ -265,7 +265,7 @@ class Config extends Setting
|
|||
*/
|
||||
public function regenerateToken($option)
|
||||
{
|
||||
$this->save(array($option => Security::generateToken()));
|
||||
$this->save(array($option => Token::getToken()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ namespace Kanboard\Model;
|
|||
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Security\Token;
|
||||
|
||||
/**
|
||||
* Project model
|
||||
|
|
@ -491,7 +491,7 @@ class Project extends Base
|
|||
$this->db
|
||||
->table(self::TABLE)
|
||||
->eq('id', $project_id)
|
||||
->save(array('is_public' => 1, 'token' => Security::generateToken()));
|
||||
->save(array('is_public' => 1, 'token' => Token::getToken()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use PicoDb\Database;
|
|||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
use Kanboard\Core\Session;
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Security\Token;
|
||||
|
||||
/**
|
||||
* User model
|
||||
|
|
@ -383,7 +383,7 @@ class User extends Base
|
|||
return $this->db
|
||||
->table(self::TABLE)
|
||||
->eq('id', $user_id)
|
||||
->save(array('token' => Security::generateToken()));
|
||||
->save(array('token' => Token::getToken()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace Schema;
|
||||
|
||||
use PDO;
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Security\Token;
|
||||
|
||||
const VERSION = 93;
|
||||
|
||||
|
|
@ -869,7 +869,7 @@ function version_20(PDO $pdo)
|
|||
function version_19(PDO $pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE config ADD COLUMN api_token VARCHAR(255) DEFAULT ''");
|
||||
$pdo->exec("UPDATE config SET api_token='".Security::generateToken()."'");
|
||||
$pdo->exec("UPDATE config SET api_token='".Token::getToken()."'");
|
||||
}
|
||||
|
||||
function version_18(PDO $pdo)
|
||||
|
|
@ -1091,6 +1091,6 @@ function version_1(PDO $pdo)
|
|||
$pdo->exec("
|
||||
INSERT INTO config
|
||||
(webhooks_token)
|
||||
VALUES ('".Security::generateToken()."')
|
||||
VALUES ('".Token::getToken()."')
|
||||
");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
namespace Schema;
|
||||
|
||||
use PDO;
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Security\Token;
|
||||
|
||||
const VERSION = 73;
|
||||
|
||||
|
|
@ -994,6 +994,6 @@ function version_1(PDO $pdo)
|
|||
$pdo->exec("
|
||||
INSERT INTO config
|
||||
(webhooks_token, api_token)
|
||||
VALUES ('".Security::generateToken()."', '".Security::generateToken()."')
|
||||
VALUES ('".Token::getToken()."', '".Token::getToken()."')
|
||||
");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Schema;
|
||||
|
||||
use Kanboard\Core\Security;
|
||||
use Kanboard\Core\Security\Token;
|
||||
use PDO;
|
||||
|
||||
const VERSION = 88;
|
||||
|
|
@ -799,7 +799,7 @@ function version_20(PDO $pdo)
|
|||
function version_19(PDO $pdo)
|
||||
{
|
||||
$pdo->exec("ALTER TABLE config ADD COLUMN api_token TEXT DEFAULT ''");
|
||||
$pdo->exec("UPDATE config SET api_token='".Security::generateToken()."'");
|
||||
$pdo->exec("UPDATE config SET api_token='".Token::getToken()."'");
|
||||
}
|
||||
|
||||
function version_18(PDO $pdo)
|
||||
|
|
@ -1068,6 +1068,6 @@ function version_1(PDO $pdo)
|
|||
$pdo->exec("
|
||||
INSERT INTO config
|
||||
(webhooks_token)
|
||||
VALUES ('".Security::generateToken()."')
|
||||
VALUES ('".Token::getToken()."')
|
||||
");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,6 +84,7 @@ class ClassProvider implements ServiceProviderInterface
|
|||
'HttpClient',
|
||||
'Lexer',
|
||||
'Request',
|
||||
'Response',
|
||||
'Router',
|
||||
'Session',
|
||||
'Template',
|
||||
|
|
@ -94,6 +95,9 @@ class ClassProvider implements ServiceProviderInterface
|
|||
'Core\Plugin' => array(
|
||||
'Hook',
|
||||
),
|
||||
'Core\Security' => array(
|
||||
'Token',
|
||||
),
|
||||
'Integration' => array(
|
||||
'BitbucketWebhook',
|
||||
'GithubWebhook',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
require_once __DIR__.'/../../Base.php';
|
||||
|
||||
use Kanboard\Core\Security\Token;
|
||||
|
||||
class TokenTest extends Base
|
||||
{
|
||||
public function testGenerateToken()
|
||||
{
|
||||
$t1 = Token::getToken();
|
||||
$t2 = Token::getToken();
|
||||
|
||||
$this->assertNotEmpty($t1);
|
||||
$this->assertNotEmpty($t2);
|
||||
|
||||
$this->assertNotEquals($t1, $t2);
|
||||
}
|
||||
|
||||
public function testCSRFTokens()
|
||||
{
|
||||
$token = new Token($this->container);
|
||||
$t1 = $token->getCSRFToken();
|
||||
|
||||
$this->assertNotEmpty($t1);
|
||||
$this->assertTrue($token->validateCSRFToken($t1));
|
||||
$this->assertFalse($token->validateCSRFToken($t1));
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue