diff --git a/api-payroll/composer.json b/api-payroll/composer.json
index e22099e..f36032b 100644
--- a/api-payroll/composer.json
+++ b/api-payroll/composer.json
@@ -17,7 +17,8 @@
"slim/php-view": "^2.0",
"monolog/monolog": "^1.17",
"respect/validation": "^1.1",
- "tuupola/cors-middleware": "^0.5.2"
+ "tuupola/cors-middleware": "^0.5.2",
+ "adbario/slim-secure-session-middleware": "^1.3"
},
"require-dev": {
"phpunit/phpunit": ">=4.8 < 6.0"
diff --git a/api-payroll/composer.lock b/api-payroll/composer.lock
index 467315f..eb078c6 100644
--- a/api-payroll/composer.lock
+++ b/api-payroll/composer.lock
@@ -4,9 +4,96 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "93a9656f4e6eb0e25be1bad59ac6f487",
- "content-hash": "a3fc18885cc45d2733b77fa2081bdc72",
+ "hash": "19bc193d641803843178e87bf0465afe",
+ "content-hash": "9eb8d110ad374a60767f92d76018504a",
"packages": [
+ {
+ "name": "adbario/php-dot-notation",
+ "version": "1.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/adbario/php-dot-notation.git",
+ "reference": "5e4b1fe29a8ae1140e370d520ed8b85dd5130a1f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/adbario/php-dot-notation/zipball/5e4b1fe29a8ae1140e370d520ed8b85dd5130a1f",
+ "reference": "5e4b1fe29a8ae1140e370d520ed8b85dd5130a1f",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Adbar\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Riku Särkinen",
+ "email": "riku@adbar.io"
+ }
+ ],
+ "description": "PHP dot notation array access",
+ "homepage": "https://github.com/adbario/php-dot-notation",
+ "keywords": [
+ "ArrayAccess",
+ "dotnotation",
+ "php"
+ ],
+ "time": "2017-03-26 17:44:47"
+ },
+ {
+ "name": "adbario/slim-secure-session-middleware",
+ "version": "1.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/adbario/slim-secure-session-middleware.git",
+ "reference": "f107191506b2c362f06f201f998891f315d6aaec"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/adbario/slim-secure-session-middleware/zipball/f107191506b2c362f06f201f998891f315d6aaec",
+ "reference": "f107191506b2c362f06f201f998891f315d6aaec",
+ "shasum": ""
+ },
+ "require": {
+ "adbario/php-dot-notation": "~1.2.0",
+ "paragonie/random_compat": "^2.0",
+ "php": ">=5.5",
+ "slim/slim": "~3.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Adbar\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Riku Särkinen",
+ "email": "riku@adbar.io"
+ }
+ ],
+ "description": "Secure session middleware for Slim 3 framework",
+ "homepage": "https://github.com/adbario/slim-secure-session-middleware",
+ "keywords": [
+ "middleware",
+ "session",
+ "slim"
+ ],
+ "time": "2017-08-04 13:51:00"
+ },
{
"name": "container-interop/container-interop",
"version": "1.2.0",
@@ -217,6 +304,55 @@
],
"time": "2018-02-13 20:26:39"
},
+ {
+ "name": "paragonie/random_compat",
+ "version": "v2.0.17",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/paragonie/random_compat.git",
+ "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d",
+ "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "4.*|5.*"
+ },
+ "suggest": {
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "lib/random.php"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paragon Initiative Enterprises",
+ "email": "security@paragonie.com",
+ "homepage": "https://paragonie.com"
+ }
+ ],
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
+ "keywords": [
+ "csprng",
+ "polyfill",
+ "pseudorandom",
+ "random"
+ ],
+ "time": "2018-07-04 16:31:37"
+ },
{
"name": "pimple/pimple",
"version": "v3.2.3",
diff --git a/api-payroll/public/html/landing.php b/api-payroll/public/html/landing.php
index eddf31b..cfbe622 100644
--- a/api-payroll/public/html/landing.php
+++ b/api-payroll/public/html/landing.php
@@ -1,12 +1,3 @@
-
-
@@ -40,10 +31,6 @@ if(!isset($_SESSION['userName'])){
Management
-
-
- Change password
-
-
diff --git a/api-payroll/public/html/login.php b/api-payroll/public/html/login.php
index 15a00e4..46f8e64 100644
--- a/api-payroll/public/html/login.php
+++ b/api-payroll/public/html/login.php
@@ -1,12 +1,3 @@
-
-
diff --git a/api-payroll/public/index.php b/api-payroll/public/index.php
index 1e2f3f1..1c08597 100644
--- a/api-payroll/public/index.php
+++ b/api-payroll/public/index.php
@@ -11,8 +11,6 @@ if (PHP_SAPI == 'cli-server') {
require __DIR__ . '/../vendor/autoload.php';
-session_start();
-
// Instantiate the app
$settings = require __DIR__ . '/../src/settings.php';
$app = new \Slim\App($settings);
diff --git a/api-payroll/public/js/landing.js b/api-payroll/public/js/landing.js
index 42a8bb5..9bb9850 100644
--- a/api-payroll/public/js/landing.js
+++ b/api-payroll/public/js/landing.js
@@ -13,12 +13,15 @@ function logout() {
window.location.replace(baseUrl + '/html/login.php');
},
error:function(x,e) {
+ let responseText = $.parseJSON(x["responseText"]);
+
if (x.status==0) {
$('#modalErrorInternetConnection').modal('show');
} else if(x.status==404) {
$('#modalError404').modal('show');
} else if(x.status==500) {
- $('#modalError500').modal('show');
+ $('#modalServerResponseError').modal('show');
+ document.getElementById('modalResponseError').innerHTML = responseText['message'];
} else if(e=='parsererror') {
$('#modalErrorParsererror').modal('show');
} else if(e=='timeout'){
@@ -59,12 +62,15 @@ function loadView(requestedView){
$("#newViewBody").hide().html(data).show('slow');
},
error:function(x,e) {
+ let responseText = $.parseJSON(x["responseText"]);
+
if (x.status==0) {
$('#modalErrorInternetConnection').modal('show');
} else if(x.status==404) {
$('#modalError404').modal('show');
} else if(x.status==500) {
- $('#modalError500').modal('show');
+ $('#modalServerResponseError').modal('show');
+ document.getElementById('modalResponseError').innerHTML = responseText['message'];
} else if(e=='parsererror') {
$('#modalErrorParsererror').modal('show');
} else if(e=='timeout'){
diff --git a/api-payroll/src/application/EmployeeApplication.php b/api-payroll/src/application/EmployeeApplication.php
index 1deb41d..3391ea3 100644
--- a/api-payroll/src/application/EmployeeApplication.php
+++ b/api-payroll/src/application/EmployeeApplication.php
@@ -9,13 +9,28 @@ class EmployeeApplication{
private $cryptographyService;
private $asserts;
private $settings;
+ private $session;
- function __construct($employeeSettings, $mysql, $cryptographyService, $asserts){
+ /**
+ * EmployeeApplication constructor.
+ * @param $employeeSettings
+ * @param $mysql
+ * @param $cryptographyService
+ * @param $asserts
+ * @param $session
+ * @throws Exception
+ */
+ function __construct($employeeSettings, $mysql, $cryptographyService, $asserts, $session){
$this->settings = $employeeSettings;
$this->cryptographyService = $cryptographyService;
$this->pdo = $mysql;
$this->asserts = $asserts;
+ $this->session = $session;
+
+ if(!$this->session->verifySession()){
+ throw new Exception('A session is requited to access this resouerce.');
+ };
}
/**
@@ -81,7 +96,6 @@ class EmployeeApplication{
} catch( PDOExecption $e ) {
$this->pdo->rollback();
throw new Exception('There was an error while trying to save a new person.');
- $this->logger->warning("There was an error in the EmployeeApplication->saveNewPerson caused by: $e ");
}
}
diff --git a/api-payroll/src/application/SessionApplication.php b/api-payroll/src/application/SessionApplication.php
index bf0bf5d..74fe3f2 100644
--- a/api-payroll/src/application/SessionApplication.php
+++ b/api-payroll/src/application/SessionApplication.php
@@ -4,11 +4,13 @@ namespace App\Application;
use Exception;
class SessionApplication{
+ private $session;
private $pdo;
private $cryptographyService;
private $asserts;
- function __construct($mysql, $cryptographyService, $asserts){
+ function __construct($session, $mysql, $cryptographyService, $asserts){
+ $this->session = $session;
$this->cryptographyService = $cryptographyService;
$this->pdo = $mysql;
$this->asserts = $asserts;
@@ -18,7 +20,8 @@ class SessionApplication{
* @return bool
*/
function verifySession(){
- return isset($_SESSION['userName']);
+ $userName = $this->session->get('userName');
+ return isset($userName);
}
/**
@@ -30,7 +33,7 @@ class SessionApplication{
$session['loggedIn'] = $this->verifySession();
if($this->verifySession()){
- $session['userName'] = $_SESSION['userName'];
+ $session['userName'] = $this->session->get('userName');
}
return $session;
@@ -83,7 +86,12 @@ class SessionApplication{
}
if($this->cryptographyService->decryptPassword($password, $storedPassword)){
- $_SESSION['userName'] = $userName;
+ $this->session->set('userName', $userName);
+
+ if(!$this->verifySession()){
+ throw new Exception('An error occurred while trying to create the session.');
+ }
+
return true;
}
else{
@@ -116,9 +124,14 @@ class SessionApplication{
/**
* @return array
+ * @throws Exception
*/
function destroySession(){
- session_destroy();
+ $this->session->clear();
+
+ if($this->verifySession()){
+ throw new Exception('An error occurred while trying to end the session.');
+ }
return array('status' => 'success', 'message' => 'Successfully logged out.');
}
diff --git a/api-payroll/src/dependencies.php b/api-payroll/src/dependencies.php
index b4246de..abed60d 100644
--- a/api-payroll/src/dependencies.php
+++ b/api-payroll/src/dependencies.php
@@ -18,6 +18,13 @@ $container['logger'] = function ($c) {
return $logger;
};
+// Session handler
+$container['session'] = function ($container) {
+ return new \Adbar\Session(
+ $container->get('settings')['session']['namespace']
+ );
+};
+
// Mysql connection
$container['mysql'] = function ($c) {
$mysqlSettings = $c->get('settings')['mysql'];
@@ -60,7 +67,8 @@ $container['asserts'] = function ($c) {
// The session application
$container['sessionApplication'] = function ($c) {
- $sessionApplication = new App\Application\SessionApplication($c['mysql'], $c['cryptographyService'], $c['asserts']);
+ $sessionApplication = new App\Application\SessionApplication($c['session'], $c['mysql'],
+ $c['cryptographyService'], $c['asserts']);
return $sessionApplication;
};
@@ -68,6 +76,6 @@ $container['sessionApplication'] = function ($c) {
$container['employeeApplication'] = function ($c) {
$employeeSettings = $c->get('settings')['employee'];
$employeeApplication = new App\Application\EmployeeApplication($employeeSettings,
- $c['mysql'], $c['cryptographyService'], $c['asserts']);
+ $c['mysql'], $c['cryptographyService'], $c['asserts'], $c['sessionApplication']);
return $employeeApplication;
};
diff --git a/api-payroll/src/middleware.php b/api-payroll/src/middleware.php
index 6898ac4..9d6b9f4 100644
--- a/api-payroll/src/middleware.php
+++ b/api-payroll/src/middleware.php
@@ -19,4 +19,6 @@ $app->add(new \Tuupola\Middleware\Cors([
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
-]));
\ No newline at end of file
+]));
+
+$app->add(new \Adbar\SessionMiddleware($app->getContainer()->get('settings')['session']));
\ No newline at end of file
diff --git a/api-payroll/src/settings.php b/api-payroll/src/settings.php
index 200cf71..165767e 100644
--- a/api-payroll/src/settings.php
+++ b/api-payroll/src/settings.php
@@ -16,6 +16,35 @@ return [
'level' => \Monolog\Logger::DEBUG,
],
+ // Session handle settings
+ 'session' => [
+ // Session cookie settings
+ 'name' => 'payroll-laziness-rocks',
+ 'lifetime' => 10,
+ 'path' => '/',
+ 'domain' => null,
+ 'secure' => false,
+ 'httponly' => true,
+
+ // Set session cookie path, domain and secure automatically
+ 'cookie_autoset' => true,
+
+ // Path where session files are stored, PHP's default path will be used if set null
+ 'save_path' => null,
+
+ // Session cache limiter
+ 'cache_limiter' => 'nocache',
+
+ // Extend session lifetime after each user activity
+ 'autorefresh' => true,
+
+ // Encrypt session data if string is set
+ 'encryption_key' => '7de431684c34cf2c898268cff71392f38c4175dde050c9ee69502b81571484e0',
+
+ // Session namespace
+ 'namespace' => 'slim'
+ ],
+
// Cryptography settings
'cryptography' => [
'encryptionAlgorithm' => 'AES-256-CBC',
diff --git a/api-payroll/tests/Functional/BaseTestCase.php b/api-payroll/tests/Functional/BaseTestCase.php
index 095d8da..f65c41f 100644
--- a/api-payroll/tests/Functional/BaseTestCase.php
+++ b/api-payroll/tests/Functional/BaseTestCase.php
@@ -20,7 +20,7 @@ class BaseTestCase extends \PHPUnit_Framework_TestCase
*
* @var bool
*/
- protected $withMiddleware = true;
+ protected $withMiddleware = false;
/**
* Process the application given a request method and URI