diff --git a/README.md b/README.md index 79ea6af..4168463 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![alt text](https://repository-images.githubusercontent.com/75949178/d960b700-5c98-11ea-813c-a94432078605 "O2System Security Atom") +![alt text](https://www.o2system.id/assets/img/covers/cover-o2system-atom-security.png "O2System Security Atom") [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/o2system/security/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/o2system/security/?branch=master) [![Build Status](https://scrutinizer-ci.com/g/o2system/security/badges/build.png?b=master)](https://scrutinizer-ci.com/g/o2system/security/build-status/master) @@ -24,7 +24,6 @@ O2System Security is a collection of class libraries to help build security proc - Binary - Cookie - Crypt via PHP's MCrypt and/or OpenSSL extensions -- Hexadecimal ### Featured Encoders - Base64 @@ -76,4 +75,4 @@ Please kindly submit your [issues at Github](http://github.com/o2system/security ### System Requirements - PHP 7.2+ - [Composer](https://getcomposer.org) -- [O2System Session](https://github.com/o2system/session) +- [O2System Session](https://github.com/o2system/session) \ No newline at end of file diff --git a/composer.json b/composer.json index cda8f04..0eb77d0 100644 --- a/composer.json +++ b/composer.json @@ -43,4 +43,4 @@ "O2System\\Security\\": "src" } } -} \ No newline at end of file +} diff --git a/src/Authentication/JsonWebToken.php b/src/Authentication/JsonWebToken.php index 454cb8e..aacdbe7 100644 --- a/src/Authentication/JsonWebToken.php +++ b/src/Authentication/JsonWebToken.php @@ -191,9 +191,8 @@ public function decode($token, $key = null) return false; } - // Check if this token has expired. - if (isset($payload->exp) && ($timestamp - $this->leeway) >= strtotime($payload->exp)) { + if (isset($payload->exp) && ($timestamp - $this->leeway) >= $payload->exp) { $this->errors[] = 'Expired token'; return false; diff --git a/src/Authentication/User.php b/src/Authentication/User.php index 34f698a..0d12e98 100644 --- a/src/Authentication/User.php +++ b/src/Authentication/User.php @@ -16,7 +16,6 @@ // ------------------------------------------------------------------------ use O2System\Cache\Item; -use O2System\Spl\DataStructures\SplArrayObject; use O2System\Spl\Traits\Collectors\ConfigCollectorTrait; use Psr\Cache\CacheItemPoolInterface; @@ -36,13 +35,13 @@ class User public function __construct() { $this->setConfig([ - 'password' => [ + 'password' => [ 'algorithm' => PASSWORD_DEFAULT, - 'options' => [], + 'options' => [], ], 'msisdnRegex' => '/^\+[1-9]{1}[0-9]{3,14}$/', 'maxAttempts' => 5, - 'sso' => [ + 'sso' => [ 'enable' => false, 'server' => base_url(), ], @@ -96,8 +95,8 @@ public function passwordRehash($password) { if (password_needs_rehash( $password, - $this->config['password']['algorithm'], - $this->config['password']['options'] + $this->config[ 'password' ][ 'algorithm' ], + $this->config[ 'password' ][ 'options' ] )) { return $this->passwordHash($password); } @@ -118,8 +117,8 @@ public function passwordHash($password) { return password_hash( $password, - $this->config['password']['algorithm'], - $this->config['password']['options'] + $this->config[ 'password' ][ 'algorithm' ], + $this->config[ 'password' ][ 'options' ] ); } @@ -145,7 +144,7 @@ public function passwordVerify($password, $hash) */ public function attempt() { - $_SESSION['userAttempts'] = $this->getAttempts() + 1; + $_SESSION[ 'userAttempts' ] = $this->getAttempts() + 1; } // ------------------------------------------------------------------------ @@ -158,8 +157,8 @@ public function attempt() public function getAttempts() { $currentAttempts = 0; - if (isset($_SESSION['userAttempts'])) { - $currentAttempts = (int)$_SESSION['userAttempts']; + if (isset($_SESSION[ 'userAttempts' ])) { + $currentAttempts = (int)$_SESSION[ 'userAttempts' ]; } return (int)$currentAttempts; @@ -167,6 +166,37 @@ public function getAttempts() // ------------------------------------------------------------------------ + /** + * User::login + * + * @param array $account + */ + public function login(array $account) + { + $_SESSION[ 'account' ] = $account; + unset($_SESSION[ 'userAttempts' ]); + } + + // ------------------------------------------------------------------------ + + /** + * User::getCacheItemPool + * + * @return CacheItemPoolInterface + */ + protected function getCacheItemPool() + { + $cacheItemPool = cache()->getObject('default'); + + if (cache()->exists('sso')) { + $cacheItemPool = cache()->getObject('sso'); + } + + return $cacheItemPool; + } + + // ------------------------------------------------------------------------ + /** * User::loggedIn * @@ -175,7 +205,29 @@ public function getAttempts() */ public function loggedIn() { - if (isset($_SESSION['account'])) { + if (isset($_SESSION[ 'account' ])) { + return true; + } elseif($this->tokenOn()) { + return true; + } elseif ($this->signedOn()) { + return true; + } + + return false; + } + + // ------------------------------------------------------------------------ + + /** + * User::tokenOn + */ + public function tokenOn() + { + if(false !== ($token = input()->bearerToken())) { + $_SESSION['account'] = (new JsonWebToken())->decode($token); + + globals()->store('account', $_SESSION['account']); + return true; } @@ -185,13 +237,28 @@ public function loggedIn() // ------------------------------------------------------------------------ /** - * AccessControl::login + * User::signedOn * - * @param array $account + * @return bool + * @throws \Psr\Cache\InvalidArgumentException */ - public function login(array $account) + public function signOn() { - $_SESSION['account'] = $account; + if ($virtualUserId = input()->cookie('ssid')) { + $cacheItemPool = $this->getCacheItemPool(); + + if($cacheItemPool->hasItem('sso-' . $virtualUserId)) { + + $item = $cacheItemPool->getItem('sso-' . input()->cookie('ssid')); + $_SESSION['account'] = $item->get(); + + globals()->store('account', $_SESSION['account']); + + return true; + } + } + + return false; } // ------------------------------------------------------------------------ @@ -201,8 +268,26 @@ public function login(array $account) */ public function logout() { - if (isset($_SESSION['account'])) { - unset($_SESSION['account']); + $this->signOff(); + + if (isset($_SESSION[ 'account' ])) { + unset($_SESSION[ 'account' ]); + } + } + + // ------------------------------------------------------------------------ + + /** + * User::signOff + * + * @throws \Psr\Cache\InvalidArgumentException + */ + public function signOff() + { + if ($virtualUserId = input()->cookie('ssid')) { + $cacheItemPool = $this->getCacheItemPool(); + $cacheItemPool->deleteItem('sso-' . $virtualUserId); + delete_cookie('ssid'); } } } \ No newline at end of file diff --git a/src/Encryptions/Binary.php b/src/Encryptions/Binary.php index d032985..294bb01 100644 --- a/src/Encryptions/Binary.php +++ b/src/Encryptions/Binary.php @@ -28,7 +28,6 @@ class Binary * @var array */ private static $charactersMap = []; - /** * Binary::$crypt * diff --git a/src/Form/Validator.php b/src/Form/Validator.php index 17fb5d8..fee4a75 100644 --- a/src/Form/Validator.php +++ b/src/Form/Validator.php @@ -360,14 +360,12 @@ protected function processRules(string $field, string $label = null, $value, $ru if ( ! $callable && preg_match('/(.*?)\[(.*)\]/', $rule, $match)) { $rule = $match[ 1 ]; - if (is_array($match[ 2 ])) { - $params = array_merge([$value], $match[ 2 ]); - } else { - $params = [$value, $match[ 2 ]]; - } + $params = $match[ 2 ]; } - if (empty($params)) { + if ($params) { + $params = array_merge([$value], $params); + } else { $params = [$value]; } @@ -386,7 +384,8 @@ protected function processRules(string $field, string $label = null, $value, $ru $error = $this->customErrors[ $field ][ $rule ]; } - $this->errors[ $field ] = is_null($error) ? $this->getErrorMessage($rule, $field, $label, $value) : $error; + $this->errors[ $field ] = is_null($error) ? $this->getErrorMessage($rule, $field, $label, + $params) : $error; return false; } @@ -444,11 +443,11 @@ public function getError(string $field = null): string * @param string $rule * @param string $field * @param string|null $label - * @param string $value + * @param string $param * * @return string */ - protected function getErrorMessage(string $rule, string $field, string $label = null, string $value = null): string + protected function getErrorMessage(string $rule, string $field, string $label = null, string $param = null): string { // Check if custom message has been defined by user if (isset($this->customErrors[ $field ][ $rule ])) { @@ -461,7 +460,7 @@ protected function getErrorMessage(string $rule, string $field, string $label = } $message = str_replace('{field}', $label ?? $field, $message); - $message = str_replace('{value}', $value ?? null, $message); + $message = str_replace('{param}', $this->rules[ $param ][ 'label' ] ?? $param, $message); return $message; }