'brokers', 'customer' => 'customers', 'commercial_lead' => 'commercial_leads', 'supplier' => 'suppliers' ]; private static $validationUsername = ''; function __construct($authToken = null){ if($authToken){ self::$authToken = str_replace('Bearer ', '', $authToken); self::$isLoggedIn = self::validateAccessToken(self::$authToken); }else{ self::$isLoggedIn = self::validateSession(); } } public function getTableByUser($userType){ return self::$userTypesTableKeys[$userType]; } private static function validateSession(){ session_start(); if(isset($_SESSION['data'])){ self::$userInfo = $_SESSION['data']; return true; } return false; } private static function validateAccessToken($authToken){ $secretKey = base64_decode(JWT_API_SECRET_KEY); try { $decodedJWT = JWT::decode($authToken, $secretKey, array(JWT_ALGORITHM)); self::$userInfo = (array) $decodedJWT->data; return true; } catch (Exception $e) { self::$userInfo['errorMessage'] = $e->getMessage(); return false; } } /** * genereates a has for a password string. The value is 60 charactes MAX due to options * @param String $password password to be hashed * @return Sting 60 characters long hashed string */ public static function hashPassword($password){ $hashOptions = [ 'cost' => 12 ]; return password_hash($password, PASSWORD_BCRYPT, $hashOptions); } public static function generateApiToken($userInfo){ $tokenId = base64_encode(random_bytes(32)); $issuedAt = time(); $notBefore = $issuedAt; $expire = $notBefore + JWT_MAX_LIFE; // 1 hour $serverName = WIAAS_URL; $data = [ 'iat' => $issuedAt, // Issued at: time when the token was generated 'jti' => $tokenId, // Json Token Id: an unique identifier for the token 'iss' => $serverName, // Issuer 'nbf' => $notBefore, // Not before 'exp' => $expire, // Expire 'data' => $userInfo, 'type' => 'authorization_token' //Token type ]; $secretKey = base64_decode(JWT_API_SECRET_KEY); $jwt = JWT::encode( $data, $secretKey, JWT_ALGORITHM ); return $jwt; } public function getRefreshToken() { global $database; $sql = "SELECT u.refresh_token FROM ".TABLES['users']." u WHERE id=".self::$userInfo['wiaas_id_user']; $result = $database->fetchResultArray($sql); return isset($result[0]) ? $result[0]['refresh_token'] : false; } private static function saveRefreshToken($userInfo, $refreshJwt){ global $database; $sql = "UPDATE ".TABLES['users']." SET refresh_token='$refreshJwt' WHERE id=".$userInfo['wiaas_id_user']; $query = $database->query($sql); return $database->affectedRows() > 0; } private static function generateRefreshToken($userInfo){ global $user; $tokenId = base64_encode(random_bytes(32)); $issuedAt = time(); $notBefore = $issuedAt; $expire = $notBefore + (JWT_MAX_LIFE * 2); // 1 hour $serverName = WIAAS_URL; $data = [ 'iat' => $issuedAt, // Issued at: time when the token was generated 'jti' => $tokenId, // Json Token Id: an unique identifier for the token 'iss' => $serverName, // Issuer 'nbf' => $notBefore, // Not before 'exp' => $expire, // Expire 'type' => 'refresh_token', //Token type 'data' => $userInfo ]; $secretKey = base64_decode(JWT_API_SECRET_KEY); $jwt = JWT::encode( $data, $secretKey, JWT_ALGORITHM ); self::saveRefreshToken($userInfo, $jwt); return $jwt; } public function getUserInfo() { return self::$userInfo; } /** * reutnrs if user is logged in * @return boolean returns if a user is logged in */ public static function isLoggedIn(){ return self::$isLoggedIn; } /** * login processing * @param String $username username * @param String $password password * @return boolean true if the user is logged in */ public static function login($username, $password, $withToken = false){ global $database; $username = $database->escapeValue($username); $password = $database->escapeValue($password); if(empty($username) OR empty($password)){ return ['status' => 'fail', 'errorMessage' => 'INVALID_USERNAME_PASSWORD']; } $sql = "SELECT u.id, u.username, u.password, ut.type, ut.id as idUserType, isCompanyAdmin FROM ".TABLES['users']." u INNER JOIN ".TABLES['rel_user_type']." rel_ut ON rel_ut.idUser=u.id INNER JOIN ".TABLES['user_types']." ut ON ut.id=rel_ut.idType WHERE u.username='".$username."' LIMIT 1"; $query = $database->query($sql); if($database->numRows($query) !== 1){ self::$isLoggedIn = false; return ['status' => 'fail', 'errorMessage' => 'INVALID_USERNAME_PASSWORD']; } $row = $database->fetchArray($query); if(!password_verify($password, $row['password'])){ return ['status' => 'fail', 'errorMessage' => 'INVALID_USERNAME_PASSWORD']; } $userTypeInfo = self::getUserTypeInfo($row['id'], $row['type']); if(count($userTypeInfo) === 0){ return ['status' => 'fail', 'errorMessage' => 'invalid user type '.$row['type'].'. Add type in User class or add the user in the correct table!']; } self::$userInfo['wiaas_id_user'] = $row['id']; self::$userInfo['wiaas_username'] = $row['username']; self::$userInfo['wiaas_user_type'] = $row['type']; self::$userInfo['wiaas_id_user_type'] = $row['idUserType']; self::$userInfo['wiaas_user_full_name'] = $userTypeInfo['fullName']; self::$userInfo['wiaas_is_company_admin'] = $row['isCompanyAdmin'] === '1' ? true : false; self::$isLoggedIn = true; if($withToken){ self::$authToken = self::generateApiToken(self::$userInfo); $refreshToken = self::generateRefreshToken(self::$userInfo); return ['status' => 'success', 'accessToken' => self::$authToken, 'refreshToken' => $refreshToken]; }else{ $_SESSION['data'] = self::$userInfo; return ['status' => 'success']; } } public function refreshToken($refreshToken, $lastActivity){ $inactivity = time() - (intval($lastActivity) / 1000); $maxInactivity = 30 * 60; // 30 minutes if($inactivity > $maxInactivity){//session expires if invactivity is more than 30 minutes return ['status' => 'error', 'errorMessage' => 'EXPIRED_SESSION']; } if(self::validateAccessToken($refreshToken)){ self::$authToken = self::generateApiToken(self::$userInfo); $refreshToken = self::generateRefreshToken(self::$userInfo); return ['status' => 'success', 'accessToken' => self::$authToken, 'refreshToken' => $refreshToken]; } return ['status' => 'error', 'errorMessage' => 'INVALID_REFRESH_TOKEN', 'extra' => $this->getErrorMessage()]; } public static function setLastActivity(){ $_SESSION['LAST_ACTIVITY'] = time(); } public static function getLastActivity(){ return $_SESSION['LAST_ACTIVITY']; } /** * get extra info for connected user by user type * @param Int $idUser id of the user * @param string $userType the type of the user * @return [Array] retruns an empty array if no info or an array with the info */ private static function getUserTypeInfo($idUser, $userType){ global $database; if(!array_key_exists($userType, self::$userTypesTableKeys)){ return []; } $sql = "SELECT info.name AS fullName FROM ".TABLES[self::$userTypesTableKeys[$userType]]." info WHERE idUser=".$idUser." LIMIT 1"; $query = $database->query($sql); if($database->numRows($query) !== 1){ return []; } $row = $database->fetchArray($query); return $row; } public function logout(){ session_unset(); session_destroy(); header("location:index.php"); } /** * get the logged username * @return String Username */ public function getUser(){ return isset(self::$userInfo['wiaas_username']) ? self::$userInfo['wiaas_username'] : false; } /** * get the logged id user * @return String id suer */ public function getUserId(){ return isset(self::$userInfo['wiaas_id_user']) ? self::$userInfo['wiaas_id_user'] : 0; } /** * get the logged user full name * @return String full name */ public function getUserFullName(){ return isset(self::$userInfo['wiaas_user_full_name']) ? self::$userInfo['wiaas_user_full_name'] : false; } /** * get the user type * @return String returns the user type */ public function getUserType(){ return isset(self::$userInfo['wiaas_user_type']) ? self::$userInfo['wiaas_user_type'] : false; } /** * get the user type id * @return String returns the user type id */ public function getIdUserType(){ return isset(self::$userInfo['wiaas_id_user_type']) ? self::$userInfo['wiaas_id_user_type'] : 0; } public function getErrorMessage(){ return isset(self::$userInfo['errorMessage']) ? self::$userInfo['errorMessage'] : ''; } /** * checks whether the token from the url provided is valid or not * @param String $token the token to check the url for * @return String confirmation message */ public function checkPasswordToken($token) { global $database; $sql = "SELECT u.username FROM ".TABLES['users']." u WHERE u.token='".$database->escapeValue($token)."' AND u.tokenTS <= DATE_ADD(u.tokenTS , INTERVAL 5 DAY)"; $result = $database->query($sql); if($database->numRows($result) !== 1) { return 'error'; } self::$validationUsername = $database->fetchArray($result)['username']; return 'success'; } /** * gets the username of the user that wants to reset the password * @return String username */ public function getSetPasswordUsername() { return self::$validationUsername; } /** * Resets the password for the user with the right token number * @param Array $passwords the new and confirmed passwords * @return Array with confirmation message */ public function resetPassword($passwords) { global $database; $data = []; if(self::$validationUsername) { $data = UtilsModel::changePassword($passwords, self::$validationUsername); $data['username'] = self::$validationUsername; self::$validationUsername = ''; } else { $data['messages'][] = [ 'code' => 'error', 'message' => 'USER_NOT_SET' ]; } return $data; } /** * generatates a new password for the user given * @param String $mail email of the user * @return String confirtmation message */ public static function forgotPassword($mail) { global $database; $mail = $database->escapeValue($mail); $now = new DateTime(); $now = $now->format('Y-m-d H:i:s'); $data = []; $sql = "SELECT u.username, u.mail, IF( ADDTIME(u.tokenTS, '00:05') > '".$now."', 0, 1 ) AS allowPasswordGeneration FROM ".TABLES['users']." u WHERE mail = '".$mail."'"; $userInfo = $database->fetchResultArray($sql); if(count($userInfo) == 0) { $data[] = 'NO_USER'; } foreach ($userInfo as $info) { if($info['allowPasswordGeneration'] == 1) { $messageData = UtilsModel::generateTokenForUserPassword(json_encode($info)); $data[] = 'SIGN_IN'; } else { $data[] = 'CHANGE_LATER'; } } return $data; } }