GWM : VAPT Scan Vulnerabilities
This commit is contained in:
parent
dabe60b498
commit
4d15ddb92a
@ -455,6 +455,8 @@ $routes->group("/api", ["filter" => "authJWT"], function ($routes) {
|
||||
|
||||
$routes->group("employeeRest", ['filter' => ['appSignature' , 'authJWT'] ], function ($routes) {
|
||||
|
||||
$routes->post('logout', 'RestAuthenticationController::logout');
|
||||
|
||||
// $routes->post("getVerifiedUserData", "RestAuthenticationController::getVerifiedUserData");
|
||||
|
||||
$routes->post("storeFireBase", "EmployeeRestController::storeFireBase");
|
||||
|
||||
@ -166,7 +166,14 @@ class RestAuthenticationController extends AdminController
|
||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithMobileNumber: Final employee data to verify = " . json_encode($employeeData));
|
||||
|
||||
if (isset($employeeData['employee_id']))
|
||||
{
|
||||
{
|
||||
|
||||
//check the resend otp (with in 60 seconds don't allow another otp to send)
|
||||
$check = canSendOtp($employeeData);
|
||||
if (!$check['allowed']) {
|
||||
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
|
||||
}
|
||||
|
||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithMobileNumber: Employee verified with ID = " . $employeeData['employee_id']);
|
||||
log_message('error', ' ');
|
||||
log_message('error', '************************ PRE END ********************************');
|
||||
@ -264,10 +271,11 @@ class RestAuthenticationController extends AdminController
|
||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Received Email ID = " . $email);
|
||||
|
||||
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email]);
|
||||
// print_r($empdata); die;
|
||||
|
||||
|
||||
$otp = random_int(100000, 999999);
|
||||
|
||||
//only retail policy
|
||||
if(empty($empdata)){
|
||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: No employee data found both PRE & POST");
|
||||
log_message('error', ' ');
|
||||
@ -323,8 +331,15 @@ class RestAuthenticationController extends AdminController
|
||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Using PRE data");
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (isset($employeeData['employee_id']))
|
||||
{
|
||||
//check the resend otp (with in 60 seconds don't allow another otp to send)
|
||||
$check = canSendOtp($employeeData);
|
||||
if (!$check['allowed']) {
|
||||
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
|
||||
}
|
||||
|
||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Valid employee found, generating OTP");
|
||||
|
||||
@ -578,6 +593,12 @@ class RestAuthenticationController extends AdminController
|
||||
|
||||
if ($HrData)
|
||||
{
|
||||
|
||||
//check the resend otp (with in 60 seconds don't allow another otp to send)
|
||||
$check = canSendOtp($HrData);
|
||||
if (!$check['allowed']) {
|
||||
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
|
||||
}
|
||||
|
||||
$sql = "UPDATE level_contacts SET otp = ? WHERE mobile = ? AND contact_type = 'client' AND is_active = 1";
|
||||
|
||||
@ -637,6 +658,12 @@ class RestAuthenticationController extends AdminController
|
||||
$data->otp = $otp;
|
||||
|
||||
if ($HrData) {
|
||||
|
||||
//check the resend otp (with in 60 seconds don't allow another otp to send)
|
||||
$check = canSendOtp($HrData);
|
||||
if (!$check['allowed']) {
|
||||
return $this->respond(['status' => false,'message' => 'OTP already sent. Please wait before retrying.','retry_after_seconds' => $check['retry_after'] ])->setStatusCode(429); // Too Many Requests
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1868,5 +1895,55 @@ class RestAuthenticationController extends AdminController
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function logout()
|
||||
{
|
||||
$authHeader = $this->request->getHeaderLine('Authorization');
|
||||
|
||||
if (!$authHeader) {
|
||||
return $this->respond([
|
||||
'status' => false,
|
||||
'message' => 'Authorization token missing'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Validate JWT (your hardened function)
|
||||
$result = JWTToken::validateJWT($authHeader);
|
||||
|
||||
if ($result['status'] !== true) {
|
||||
return $this->respond([
|
||||
'status' => false,
|
||||
'message' => 'Invalid or expired token'
|
||||
], 401);
|
||||
}
|
||||
|
||||
$decoded = $result['decoded'];
|
||||
$userId = $decoded['id'] ?? null;
|
||||
|
||||
if (!$userId) {
|
||||
return $this->respond([
|
||||
'status' => false,
|
||||
'message' => 'Invalid token payload'
|
||||
], 401);
|
||||
}
|
||||
|
||||
// Identify user type
|
||||
if (isset($decoded['emp_code'])) {
|
||||
$model = new EmployeeModel();
|
||||
} else {
|
||||
$model = new LevelContactModel();
|
||||
}
|
||||
|
||||
// Invalidate token server-side
|
||||
$model->update($userId, [
|
||||
'token_time_out' => null
|
||||
]);
|
||||
|
||||
return $this->respond([
|
||||
'status' => true,
|
||||
'message' => 'Logged out successfully'
|
||||
], 200);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -18,65 +18,115 @@ use App\Models\LevelContactModel;
|
||||
|
||||
class AuthJWT implements FilterInterface
|
||||
{
|
||||
// public function before(RequestInterface $request, $arguments = null)
|
||||
// {
|
||||
// $jwt = $request->getHeaderLine('Authorization');
|
||||
|
||||
// if ($jwt) {
|
||||
// if (JWTToken::validateJWT($jwt)) {
|
||||
// $data = JWTToken::validateJWT($jwt);
|
||||
// $data = json_decode($data);
|
||||
|
||||
// $id = $data->decoded->id;
|
||||
// if(isset($data->decoded->emp_code)){
|
||||
// $model = new EmployeeModel();
|
||||
// $user_data = $model->where('id', $id)->first();
|
||||
|
||||
// if($user_data['token_time_out'] > time()){
|
||||
// $data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
||||
// $model->update($id, $data);
|
||||
// return true;
|
||||
// }else{
|
||||
|
||||
// // if($user_data['token_time_out'] != "" && $user_data['token_time_out'] != NULL)
|
||||
|
||||
// $data =["token_time_out" => ''];
|
||||
// $model->update($id, $data);
|
||||
// header('Content-Type: application/json');
|
||||
// http_response_code(401);
|
||||
// // $error = json_encode(["status" => 401, "message" => $data->message]);
|
||||
// $error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
|
||||
// echo $error;
|
||||
// exit;
|
||||
// }
|
||||
// }else{
|
||||
// $model = new LevelContactModel();
|
||||
// $hr_data = $model->where('id', $id)->first();
|
||||
|
||||
// if($hr_data['token_time_out'] > time()){
|
||||
// $data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
||||
// $model->update($id, $data);
|
||||
// return true;
|
||||
// }else{
|
||||
// $data =["token_time_out" => ''];
|
||||
// $model->update($id, $data);
|
||||
// header('Content-Type: application/json');
|
||||
// http_response_code(401);
|
||||
// // $error = json_encode(["status" => 401, "message" => $data->message]);
|
||||
// $error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
|
||||
// echo $error;
|
||||
// exit;
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
// } else {
|
||||
// header('Content-Type: application/json');
|
||||
// http_response_code(403);
|
||||
// $error = json_encode(["status" => 403, "message" => "Access Forbidden!"]);
|
||||
// echo $error;
|
||||
// exit();
|
||||
// }
|
||||
// }
|
||||
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
$jwt = $request->getHeaderLine('Authorization');
|
||||
$authHeader = $request->getHeaderLine('Authorization');
|
||||
|
||||
if ($jwt) {
|
||||
if (JWTToken::validateJWT($jwt)) {
|
||||
$data = JWTToken::validateJWT($jwt);
|
||||
$data = json_decode($data);
|
||||
|
||||
$id = $data->decoded->id;
|
||||
if(isset($data->decoded->emp_code)){
|
||||
$model = new EmployeeModel();
|
||||
$user_data = $model->where('id', $id)->first();
|
||||
|
||||
if($user_data['token_time_out'] > time()){
|
||||
$data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
||||
$model->update($id, $data);
|
||||
return true;
|
||||
}else{
|
||||
|
||||
// if($user_data['token_time_out'] != "" && $user_data['token_time_out'] != NULL)
|
||||
|
||||
$data =["token_time_out" => ''];
|
||||
$model->update($id, $data);
|
||||
header('Content-Type: application/json');
|
||||
http_response_code(401);
|
||||
// $error = json_encode(["status" => 401, "message" => $data->message]);
|
||||
$error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
|
||||
echo $error;
|
||||
exit;
|
||||
}
|
||||
}else{
|
||||
$model = new LevelContactModel();
|
||||
$hr_data = $model->where('id', $id)->first();
|
||||
|
||||
if($hr_data['token_time_out'] > time()){
|
||||
$data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
||||
$model->update($id, $data);
|
||||
return true;
|
||||
}else{
|
||||
$data =["token_time_out" => ''];
|
||||
$model->update($id, $data);
|
||||
header('Content-Type: application/json');
|
||||
http_response_code(401);
|
||||
// $error = json_encode(["status" => 401, "message" => $data->message]);
|
||||
$error = json_encode(["status" => 401, "message" => "Token is Invalid"]);
|
||||
echo $error;
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
header('Content-Type: application/json');
|
||||
http_response_code(403);
|
||||
$error = json_encode(["status" => 403, "message" => "Access Forbidden!"]);
|
||||
echo $error;
|
||||
exit();
|
||||
if (!$authHeader) {
|
||||
return $this->reject(403, 'Access Forbidden');
|
||||
}
|
||||
|
||||
$result = JWTToken::validateJWT($authHeader);
|
||||
|
||||
if ($result['status'] !== true) {
|
||||
return $this->reject(401, $result['message']);
|
||||
}
|
||||
|
||||
$decoded = $result['decoded'];
|
||||
$id = $decoded['id'] ?? null;
|
||||
|
||||
if (!$id) {
|
||||
return $this->reject(401, 'Invalid token payload');
|
||||
}
|
||||
|
||||
if (isset($decoded['emp_code'])) {
|
||||
$model = new EmployeeModel();
|
||||
} else {
|
||||
$model = new LevelContactModel();
|
||||
}
|
||||
|
||||
$user = $model->find($id);
|
||||
|
||||
if (!$user || $user['token_time_out'] <= time()) {
|
||||
$model->update($id, ['token_time_out' => null]);
|
||||
return $this->reject(401, 'Token expired');
|
||||
}
|
||||
|
||||
// Refresh sliding expiration
|
||||
$model->update($id, [
|
||||
'token_time_out' => time() + getenv('TOKENTIMEOUT')
|
||||
]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function reject(int $code, string $message)
|
||||
{
|
||||
return service('response')
|
||||
->setStatusCode($code)
|
||||
->setJSON(['status' => $code, 'message' => $message])
|
||||
->send();
|
||||
}
|
||||
|
||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||
|
||||
@ -18,9 +18,13 @@ use App\Models\LevelContactModel;
|
||||
|
||||
class JWTToken
|
||||
{
|
||||
|
||||
private const ALLOWED_ALG = 'HS512';
|
||||
|
||||
|
||||
public static function encode($data =null)
|
||||
{
|
||||
$secret_Key ="secret";
|
||||
$secret_Key = env('JWT_SECRET');
|
||||
|
||||
$request_data = (array)$data;
|
||||
|
||||
@ -47,30 +51,79 @@ class JWTToken
|
||||
}
|
||||
}
|
||||
|
||||
public static function validateJWT($jwt)
|
||||
// public static function validateJWT($jwt)
|
||||
// {
|
||||
// $jwtParts = explode(' ', $jwt);
|
||||
|
||||
// // print_r($jwtParts);
|
||||
// if (count($jwtParts) != 2 || $jwtParts[0] == 'Bearer') {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// $token = $jwtParts[1];
|
||||
|
||||
// try {
|
||||
// $decoded = JWT::decode($token, new Key(env('JWT_SECRET'), 'HS512'));
|
||||
// return json_encode(['status' => true, 'message' => 'Token is valid', 'decoded' => (array) $decoded]);
|
||||
// } catch (ExpiredException $e) {
|
||||
// return json_encode(['status' => false, 'message' => 'Token has expired']);
|
||||
// } catch (BeforeValidException $e) {
|
||||
// return json_encode(['status' => false, 'message' => 'Token is not yet valid']);
|
||||
// } catch (SignatureInvalidException $e) {
|
||||
// return json_encode(['status' => false, 'message' => 'Token signature is invalid']);
|
||||
// } catch (\Exception $e) {
|
||||
// return json_encode(['status' => false, 'message' => 'An error occurred while decoding the token']);
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
public static function validateJWT(string $authHeader)
|
||||
{
|
||||
$jwtParts = explode(' ', $jwt);
|
||||
// 1️⃣ Validate Authorization header
|
||||
if (!preg_match('/^Bearer\s(\S+)$/', $authHeader, $matches)) {
|
||||
return ['status' => false, 'message' => 'Invalid Authorization header'];
|
||||
}
|
||||
|
||||
// print_r($jwtParts);
|
||||
if (count($jwtParts) != 2 || $jwtParts[0] == 'Bearer') {
|
||||
return false;
|
||||
}
|
||||
$token = $matches[1];
|
||||
|
||||
$token = $jwtParts[1];
|
||||
// 2️⃣ Decode JWT header manually
|
||||
$jwtParts = explode('.', $token);
|
||||
if (count($jwtParts) !== 3) {
|
||||
return ['status' => false, 'message' => 'Malformed JWT'];
|
||||
}
|
||||
|
||||
try {
|
||||
$decoded = JWT::decode($token, new Key("secret", 'HS512'));
|
||||
return json_encode(['status' => true, 'message' => 'Token is valid', 'decoded' => (array) $decoded]);
|
||||
} catch (ExpiredException $e) {
|
||||
return json_encode(['status' => false, 'message' => 'Token has expired']);
|
||||
} catch (BeforeValidException $e) {
|
||||
return json_encode(['status' => false, 'message' => 'Token is not yet valid']);
|
||||
} catch (SignatureInvalidException $e) {
|
||||
return json_encode(['status' => false, 'message' => 'Token signature is invalid']);
|
||||
} catch (\Exception $e) {
|
||||
return json_encode(['status' => false, 'message' => 'An error occurred while decoding the token']);
|
||||
}
|
||||
$header = json_decode(base64_decode(strtr($jwtParts[0], '-_', '+/')), true);
|
||||
|
||||
// 3️⃣ Reject missing or NONE algorithm
|
||||
if (
|
||||
empty($header['alg']) ||
|
||||
$header['alg'] === 'none' ||
|
||||
$header['alg'] !== self::ALLOWED_ALG
|
||||
) {
|
||||
return ['status' => false, 'message' => 'Invalid or unsupported JWT algorithm'];
|
||||
}
|
||||
|
||||
// 4️⃣ Enforce signature validation
|
||||
try {
|
||||
$decoded = JWT::decode(
|
||||
$token,
|
||||
new Key(env('JWT_SECRET'), self::ALLOWED_ALG)
|
||||
);
|
||||
|
||||
return [
|
||||
'status' => true,
|
||||
'decoded' => (array) $decoded
|
||||
];
|
||||
|
||||
} catch (ExpiredException $e) {
|
||||
return ['status' => false, 'message' => 'Token expired'];
|
||||
} catch (BeforeValidException $e) {
|
||||
return ['status' => false, 'message' => 'Token not yet valid'];
|
||||
} catch (SignatureInvalidException $e) {
|
||||
return ['status' => false, 'message' => 'Invalid token signature'];
|
||||
} catch (\Exception $e) {
|
||||
return ['status' => false, 'message' => 'Token validation failed'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -666,3 +666,29 @@ if (!function_exists('check_pay_by_employee_or_company')) {
|
||||
|
||||
}
|
||||
|
||||
if (!function_exists('canSendOtp')) {
|
||||
function canSendOtp(array $row, int $limitSeconds = 60): array
|
||||
{
|
||||
// If OTP does not exist → allow
|
||||
if (empty($row['otp']) || empty($row['updated_at'])) {
|
||||
return ['allowed' => true];
|
||||
}
|
||||
|
||||
$lastUpdated = strtotime($row['updated_at']);
|
||||
$currentTime = time();
|
||||
|
||||
// Calculate expiry time
|
||||
$allowedAfter = $lastUpdated + $limitSeconds;
|
||||
|
||||
// If still within limit → block
|
||||
if ($currentTime < $allowedAfter) {
|
||||
return [
|
||||
'allowed' => false,
|
||||
'retry_after' => $allowedAfter - $currentTime
|
||||
];
|
||||
}
|
||||
|
||||
return ['allowed' => true];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user