diff --git a/src/Services/SSOService.php b/src/Services/SSOService.php index 8094f48..85f40fd 100644 --- a/src/Services/SSOService.php +++ b/src/Services/SSOService.php @@ -173,10 +173,6 @@ protected function getState() */ public function retrieveToken() { - if (session_status() === PHP_SESSION_NONE) { - session_start(); - } - if (isset($_SESSION[self::SSO_SESSION_IMPERSONATE])) { return $_SESSION[self::SSO_SESSION_IMPERSONATE]; } else if (isset($_SESSION[self::SSO_SESSION])) { @@ -204,7 +200,7 @@ public function retrieveImpersonateToken() public function saveToken($credentials) { if (session_status() === PHP_SESSION_NONE) { - session_start(); + throw new Exception("Cannot save token. Please start session!", 500); } $decoded_access_token = (new AccessToken($credentials))->parseAccessToken(); @@ -229,19 +225,17 @@ public function saveToken($credentials) */ public function forgetToken() { - if (session_status() === PHP_SESSION_NONE) { - session_start(); - } - // Remove all session variables. if (isset($_SESSION[self::SSO_SESSION_IMPERSONATE])) { $this->forgetImpersonateToken(); - } else { + } else if (isset($_SESSION[self::SSO_SESSION])) { unset($_SESSION[self::SSO_SESSION]); } // Destroy the session - session_destroy(); + if (session_status() === PHP_SESSION_ACTIVE) { + session_destroy(); + } } /** @@ -262,8 +256,9 @@ public function forgetImpersonateToken() public function validateState($state) { if (session_status() === PHP_SESSION_NONE) { - session_start(); + throw new Exception("Cannot validate state. Please start session!", 500); } + $challenge = $_SESSION[self::SSO_SESSION_STATE]; return (! empty($state) && ! empty($challenge) && $challenge === $state); } @@ -276,8 +271,9 @@ public function validateState($state) public function saveState() { if (session_status() === PHP_SESSION_NONE) { - session_start(); + throw new Exception("Cannot save state. Please start session!", 500); } + $_SESSION[self::SSO_SESSION_STATE] = $this->state; } @@ -288,15 +284,13 @@ public function saveState() */ public function forgetState() { - if (session_status() === PHP_SESSION_NONE) { - session_start(); + if (session_status() === PHP_SESSION_ACTIVE) { + // Remove all session variables. + session_unset(); + + // Destroy the session + session_destroy(); } - - // Remove all session variables. - session_unset(); - - // Destroy the session - session_destroy(); } /** diff --git a/stubs/ci3/controllers/Webauth.php b/stubs/ci3/controllers/Webauth.php index dbee961..0d895f2 100644 --- a/stubs/ci3/controllers/Webauth.php +++ b/stubs/ci3/controllers/Webauth.php @@ -4,15 +4,14 @@ use RistekUSDI\SSO\PHP\Exceptions\CallbackException; use RistekUSDI\SSO\PHP\Services\SSOService; use RistekUSDI\SSO\PHP\Auth\Guard\WebGuard; -use RistekUSDI\SSO\PHP\Auth\AccessToken; class Webauth extends CI_Controller { public function __construct() { parent::__construct(); - $this->CI =& get_instance(); $this->load->helper('url'); + $this->load->library('session'); } public function login() @@ -60,7 +59,7 @@ public function callback() // You may need to create a custom session for your internal app $this->createSession(); - redirect('/home'); + redirect('home', 'location', 301); } catch (\Exception $e) { throw new CallbackException($e->getCode(), $e->getMessage()); } @@ -82,7 +81,7 @@ public function impersonate() $this->createSession(); - redirect('/home'); + redirect('home', 'location', 301); } catch (\Throwable $th) { echo "Status code: {$th->getCode()} \n"; echo "Error message: {$th->getMessage()}\n"; @@ -90,43 +89,57 @@ public function impersonate() } } + /** + * You may be create a session to get roles and permission that belongs to each role. + * After user logged in, they may have list of roles based on a client (app) that stored in client_roles property. + * Use "client_roles" property as parameter to get roles and permissions in your app database. + * Expected result is a serialize of array that store in a session called serialize session. + * The array contains: + * - roles (list of roles with permissions belongs to each role) + * - role (active or current role) + */ private function createSession() { $client_roles = (new WebGuard)->user()->client_roles; + + $roles = $this->db->query("SELECT role_id AS id, role_name as `name` FROM rbac_roles + WHERE rbac_roles.role_name IN ?", array($client_roles))->result(); + + foreach ($roles as $key => $role) { + $role_permissions = $this->db->query("SELECT rbac_permissions.perm_desc + FROM rbac_permissions + INNER JOIN rbac_role_perm ON rbac_role_perm.perm_id = rbac_permissions.perm_id + WHERE rbac_role_perm.`role_id` = ?", array($role->id))->result_array(); + + $roles[$key]->permissions = array_column($role_permissions, 'perm_desc'); + } + // NOTE: You maybe want to get roles from your database by using $client_roles // and put permissions to each role. - // Here's is example of result. - $roles = json_decode(json_encode([ - [ - 'id' => 1, - 'name' => 'Operator', - 'permissions' => [ - 'user:view', - 'user:edit', - ] - ], - [ - 'id' => 2, - 'name' => 'User', - 'permissions' => [ - 'profile:view', - 'profile:edit', - ] - ], - ])); + // Here's is the expected result. + // $roles = json_decode(json_encode([ + // [ + // 'id' => 1, + // 'name' => 'Operator', + // 'permissions' => [ + // 'user:view', + // 'user:edit', + // ] + // ], + // [ + // 'id' => 2, + // 'name' => 'User', + // 'permissions' => [ + // 'profile:view', + // 'profile:edit', + // ] + // ], + // ])); - $serialize_session = serialize(array( + $_SESSION['serialize_session'] = serialize(array( 'roles' => $roles, - 'role' => $roles[0], - )); - - // PHP_SESSION_NONE if sessions are enabled, but none exists. - // https://www.php.net/manual/en/function.session-status.php - if (session_status() === PHP_SESSION_NONE) { - session_start(); - } - - $_SESSION['serialize_session'] = $serialize_session; + 'role' => $roles[0], // This is a active or current role + )); } /** diff --git a/stubs/ci3/libraries/Webguard.php b/stubs/ci3/libraries/Webguard.php index 5cc59f8..54a1df9 100644 --- a/stubs/ci3/libraries/Webguard.php +++ b/stubs/ci3/libraries/Webguard.php @@ -1,16 +1,18 @@ ci = $ci; + $this->ci->load->library('session'); $this->user = (new Guard)->user(); } @@ -26,7 +28,13 @@ public function authenticated() public function check() { - return (new Guard())->check(); + $credentials = (new SSOService())->retrieveToken(); + if ($credentials) { + $user = (new SSOService)->getUserProfile($credentials); + return $user ? true : false; + } else { + return false; + } } public function guest() @@ -48,55 +56,23 @@ public function get() return $this->user; } - /** - * Check if user has specific role - * @return boolean - */ - public function hasRole($role) + public function hasRole($roles) { - $result = false; - $roles_attr = $this->user->roles; - $role_names = array_column($roles_attr, 'name'); - if (is_array($role)) { - $roles = $role; - $result = !empty(array_intersect($role_names , (array) $roles)); - } else { - $result = in_array($role, $role_names) ? true : false; - } - + $result = empty(array_diff((array) $roles, $this->user()->get()->roles)); $this->user->hasRole = $result; return $this->user->hasRole; } - /** - * Check if user has permission(s) from specific role - * @return boolean - */ - public function hasPermission($permission) + public function hasPermission($permissions) { - $result = false; - $role_permissions = []; - if (isset($this->user->role->permissions)) { - foreach ($this->user->role->permissions as $perm) { - array_push($role_permissions, $perm); - } - } - - if (is_array($permission)) { - $permissions = $permission; - - $result = !empty(array_intersect((array) $role_permissions, (array) $permissions)); - } else { - $result = in_array($permission, $role_permissions) ? true : false; - } - + $result = !empty(array_intersect((array) $permissions, $this->user->role->permissions)); $this->user->hasPermission = $result; return $this->user->hasPermission; } - - public function restrictAjax() + + public function restrictAjaxLogin() { - if (!$this->is_logged_in()) { + if (!$this->check()) { $response['submit'] = 403; $response['error'] = 'Your session has been expired, please login again'; header('Content-Type: application/json; charset=utf-8');