diff --git a/api/v2/authorization.php b/api/v2/authorization.php index 37395d4..aff98dd 100644 --- a/api/v2/authorization.php +++ b/api/v2/authorization.php @@ -70,6 +70,11 @@ if ($stmt->rowCount() == 1) { $stmt_service->execute([$user_data['service'], $user_data['id']]); } + $user_data['refreshkey'] = bin2hex(random_bytes(25)); + $sql_refreshkey = 'UPDATE users SET refreshkey = ? WHERE id = ?'; + $stmt_service = $pdo->prepare($sql_refreshkey); + $stmt_service->execute([$user_data['refreshkey'], $user_data['id']]); + $token = createCommunicationToken($user_data['userkey']); //RETURN JWT AND CLIENTSECRET @@ -78,6 +83,7 @@ if ($stmt->rowCount() == 1) { 'token' => $token, 'token_valid' => date('Y-m-d H:i:s',time() + 1800), 'userkey' => $user_data['userkey'], + 'refreshkey' => $user_data['refreshkey'], 'language' => $user_data['language'] ); diff --git a/api/v2/get/token_refresh.php b/api/v2/get/token_refresh.php new file mode 100644 index 0000000..4bb278d --- /dev/null +++ b/api/v2/get/token_refresh.php @@ -0,0 +1,93 @@ + 'API_INPUT_1','error' => 'refreshkey is required'])); +} + +//GET USER_DATA +$stmt = $pdo->prepare('SELECT * FROM users WHERE refreshkey = ?'); +$stmt->execute([$token_refresh]); + +if ($stmt->rowCount() == 1) { + //Get results + $user_data = $stmt->fetch(); + + //Check valid userkey + $valid_key = strtotime('+30 minutes',strtotime($user_data['lastlogin'])); + $valid = ($valid_key <= time())?0:1; + + //REFRESH USERKEY + if ($user_data['userkey'] != '' && $valid == 0){ + $user_data['userkey'] = bin2hex(random_bytes(25)); + $sql_userkey = 'UPDATE users SET userkey = ? WHERE id = ?'; + $stmt_userkey = $pdo->prepare($sql_userkey); + $stmt_userkey->execute([$user_data['userkey'], $user_data['id']]); + } + + //REFRESH USERKEY + if ($user_data['service'] != '' && $valid == 0){ + $user_data['service'] = bin2hex(random_bytes(25)); + $sql_service = 'UPDATE users SET service = ? WHERE id = ?'; + $stmt_service = $pdo->prepare($sql_service); + $stmt_service->execute([$user_data['service'], $user_data['id']]); + } + + //Refresh REFRESHKEY + $user_data['refreshkey'] = bin2hex(random_bytes(25)); + $sql_refreshkey = 'UPDATE users SET refreshkey = ? WHERE id = ?'; + $stmt_service = $pdo->prepare($sql_refreshkey); + $stmt_service->execute([$user_data['refreshkey'], $user_data['id']]); + + $token = createCommunicationToken($user_data['userkey']); + + //RETURN JWT AND CLIENTSECRET + $user = array( + 'clientID' => $user_data['username'], + 'token' => $token, + 'token_valid' => date('Y-m-d H:i:s',time() + 1800), + 'userkey' => $user_data['userkey'], + 'refreshkey' => $user_data['refreshkey'], + 'language' => $user_data['language'] + ); + + //+++++++++++++++++++++++++++++++++++++++++++ + //Return as JSON + //+++++++++++++++++++++++++++++++++++++++++++ + echo json_encode($user, JSON_UNESCAPED_UNICODE); +} +else { + http_response_code(404); + exit(json_encode(['error_code' => 'API_NOT_FOUND','error' => 'Refresh not succesfull'])); +} + +?> \ No newline at end of file diff --git a/assets/database/STEP 2.sql b/assets/database/STEP 2.sql index f056afa..c72ceee 100644 --- a/assets/database/STEP 2.sql +++ b/assets/database/STEP 2.sql @@ -919,5 +919,7 @@ UPDATE equipment SET warranty_date = DATE_ADD(warranty_date, INTERVAL 1 YEAR) WHERE warranty_date IS NOT NULL; +alter table users add refreshkey varchar(255); + SET FOREIGN_KEY_CHECKS=1; \ No newline at end of file diff --git a/assets/functions.php b/assets/functions.php index dc49da7..340069c 100644 --- a/assets/functions.php +++ b/assets/functions.php @@ -1725,6 +1725,7 @@ function getProfile($profile, $permission){ // Always allowed collections: [collection => allowed_actions_string] $always_allowed = [ 'com_log' => 'CRU', + 'token_refresh' => 'R', 'application' => 'CRU', 'user_roles' => 'R', 'user_role_assignments' => 'R', diff --git a/index.php b/index.php index 0ba5fd8..10db0a9 100644 --- a/index.php +++ b/index.php @@ -41,6 +41,42 @@ include dirname(__FILE__).'/assets/functions.php'; include dirname(__FILE__).'/settings/settings_redirector.php'; include_once dirname(__FILE__).'/settings/countries.php'; +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +//TOKEN REFRESH LOGIC +//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// Token refresh buffer: refresh token 5 minutes (300 seconds) before expiry +$token_refresh_buffer = 300; + +// Check if API token exists and is still valid +if (!isset($_SESSION['authorization']['userkey']) || + !isset($_SESSION['authorization']['token_valid']) || + time() >= (strtotime($_SESSION['authorization']['token_valid']) - $token_refresh_buffer)) { + + // Token missing, expired, or about to expire - get new token + if (isset($_SESSION['authorization']['refreshkey'])) { + $api_url = '/v2/token_refresh?refreshkey='.$_SESSION['authorization']['refreshkey']; + $responses = ioServer($api_url, ''); + + //Decode Payload + if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = null;} + + if (isset($responses['userkey']) && isset($responses['token_valid'])) { + // Update session with complete response (same as login.php) + $_SESSION['authorization'] = $responses; + } else { + // Token refresh failed - redirect to login + session_destroy(); + header('location: login.php?error=session_expired'); + die(); + } + } else { + // No refreshkey available - redirect to login + session_destroy(); + header('location: login.php?error=session_expired'); + die(); + } +} + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //GET USER PERMISSION ASSIGNED //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++