Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
e34ac2f955
@ -456,6 +456,8 @@ $routes->group("/api", ["filter" => "authJWT"], function ($routes) {
|
|||||||
|
|
||||||
$routes->group("employeeRest", ['filter' => ['appSignature' , 'authJWT'] ], function ($routes) {
|
$routes->group("employeeRest", ['filter' => ['appSignature' , 'authJWT'] ], function ($routes) {
|
||||||
|
|
||||||
|
$routes->post('logout', 'RestAuthenticationController::logout');
|
||||||
|
|
||||||
// $routes->post("getVerifiedUserData", "RestAuthenticationController::getVerifiedUserData");
|
// $routes->post("getVerifiedUserData", "RestAuthenticationController::getVerifiedUserData");
|
||||||
|
|
||||||
$routes->post("storeFireBase", "EmployeeRestController::storeFireBase");
|
$routes->post("storeFireBase", "EmployeeRestController::storeFireBase");
|
||||||
|
|||||||
@ -167,6 +167,13 @@ class RestAuthenticationController extends AdminController
|
|||||||
|
|
||||||
if (isset($employeeData['employee_id']))
|
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']);
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithMobileNumber: Employee verified with ID = " . $employeeData['employee_id']);
|
||||||
log_message('error', ' ');
|
log_message('error', ' ');
|
||||||
log_message('error', '************************ PRE END ********************************');
|
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);
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Received Email ID = " . $email);
|
||||||
|
|
||||||
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email]);
|
$empdata = RestAuthHelper::getPreAndPostDataByEmailOrMobile(['email_id' => $email]);
|
||||||
// print_r($empdata); die;
|
|
||||||
|
|
||||||
$otp = random_int(100000, 999999);
|
$otp = random_int(100000, 999999);
|
||||||
|
|
||||||
|
//only retail policy
|
||||||
if(empty($empdata)){
|
if(empty($empdata)){
|
||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: No employee data found both PRE & POST");
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: No employee data found both PRE & POST");
|
||||||
log_message('error', ' ');
|
log_message('error', ' ');
|
||||||
@ -323,8 +331,15 @@ class RestAuthenticationController extends AdminController
|
|||||||
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Using PRE data");
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Using PRE data");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (isset($employeeData['employee_id']))
|
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");
|
$this->myLogger->logme("error", "REST-AUTH-CONTROLLER - verifyEmployeeWithEmailId: Valid employee found, generating OTP");
|
||||||
|
|
||||||
@ -579,6 +594,12 @@ class RestAuthenticationController extends AdminController
|
|||||||
if ($HrData)
|
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";
|
$sql = "UPDATE level_contacts SET otp = ? WHERE mobile = ? AND contact_type = 'client' AND is_active = 1";
|
||||||
|
|
||||||
$db = db_connect();
|
$db = db_connect();
|
||||||
@ -638,6 +659,12 @@ class RestAuthenticationController extends AdminController
|
|||||||
|
|
||||||
if ($HrData) {
|
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 = "
|
$sql = "
|
||||||
@ -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,116 @@ use App\Models\LevelContactModel;
|
|||||||
|
|
||||||
class AuthJWT implements FilterInterface
|
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)
|
public function before(RequestInterface $request, $arguments = null)
|
||||||
{
|
{
|
||||||
$jwt = $request->getHeaderLine('Authorization');
|
$authHeader = $request->getHeaderLine('Authorization');
|
||||||
|
|
||||||
if ($jwt) {
|
if (!$authHeader) {
|
||||||
if (JWTToken::validateJWT($jwt)) {
|
return $this->reject(403, 'Access Forbidden');
|
||||||
$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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$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 {
|
} else {
|
||||||
$model = new LevelContactModel();
|
$model = new LevelContactModel();
|
||||||
$hr_data = $model->where('id', $id)->first();
|
$id = $decoded['pre_hr_id'] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$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')
|
||||||
|
]);
|
||||||
|
|
||||||
if($hr_data['token_time_out'] > time()){
|
|
||||||
$data =["token_time_out" => time() + getenv('TOKENTIMEOUT') ];
|
|
||||||
$model->update($id, $data);
|
|
||||||
return true;
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
private function reject(int $code, string $message)
|
||||||
} else {
|
{
|
||||||
header('Content-Type: application/json');
|
return service('response')
|
||||||
http_response_code(403);
|
->setStatusCode($code)
|
||||||
$error = json_encode(["status" => 403, "message" => "Access Forbidden!"]);
|
->setJSON(['status' => $code, 'message' => $message])
|
||||||
echo $error;
|
->send();
|
||||||
exit();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||||
|
|||||||
@ -18,9 +18,13 @@ use App\Models\LevelContactModel;
|
|||||||
|
|
||||||
class JWTToken
|
class JWTToken
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private const ALLOWED_ALG = 'HS512';
|
||||||
|
|
||||||
|
|
||||||
public static function encode($data =null)
|
public static function encode($data =null)
|
||||||
{
|
{
|
||||||
$secret_Key ="secret";
|
$secret_Key = env('JWT_SECRET');
|
||||||
|
|
||||||
$request_data = (array)$data;
|
$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)) {
|
||||||
// print_r($jwtParts);
|
return ['status' => false, 'message' => 'Invalid Authorization header'];
|
||||||
if (count($jwtParts) != 2 || $jwtParts[0] == 'Bearer') {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$token = $jwtParts[1];
|
$token = $matches[1];
|
||||||
|
|
||||||
|
// 2️⃣ Decode JWT header manually
|
||||||
|
$jwtParts = explode('.', $token);
|
||||||
|
if (count($jwtParts) !== 3) {
|
||||||
|
return ['status' => false, 'message' => 'Malformed JWT'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$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 {
|
try {
|
||||||
$decoded = JWT::decode($token, new Key("secret", 'HS512'));
|
$decoded = JWT::decode(
|
||||||
return json_encode(['status' => true, 'message' => 'Token is valid', 'decoded' => (array) $decoded]);
|
$token,
|
||||||
} catch (ExpiredException $e) {
|
new Key(env('JWT_SECRET'), self::ALLOWED_ALG)
|
||||||
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']);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -677,6 +677,32 @@ 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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!function_exists('getLatestGMCPolicy')) {
|
if (!function_exists('getLatestGMCPolicy')) {
|
||||||
|
|
||||||
function getLatestGMCPolicy(array $empPolicy)
|
function getLatestGMCPolicy(array $empPolicy)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user