diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 492f2d2..8bef71b 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -10,14 +10,17 @@ $routes->options('(:any)', function() { }); $routes->get('/', 'Home::index'); +//PUNYA GUS INI TEMP $routes->get('/api/v1/emr/lab/list-new', 'NUHATEMP::index'); $routes->post('/api/v1/emr/lab/insert', 'NUHATEMP::create'); $routes->post('/api/v1/emr/lab/update-validasi', 'NUHATEMP::update'); $routes->post('/api/v1/emr/lab/detail', 'NUHATEMP::detail'); -$routes->post('/auth/login/', 'Auth::login'); -$routes->post('/auth/change_pass/', 'Auth::change_pass'); -$routes->post('/auth/register/', 'Auth::register'); +$routes->post('/api/auth/login/', 'Auth::login'); +$routes->post('/api/auth/change_pass/', 'Auth::change_pass'); +$routes->post('/api/auth/register/', 'Auth::register'); +$routes->get('/api/auth/check/', 'Auth::checkAuth'); +$routes->post('/api/auth/logout/', 'Auth::logout'); $routes->get('/api/patient', 'Patient::index'); $routes->post('/api/patient', 'Patient::create'); diff --git a/app/Controllers/Auth.php b/app/Controllers/Auth.php index ff41e0d..7f04e11 100644 --- a/app/Controllers/Auth.php +++ b/app/Controllers/Auth.php @@ -5,6 +5,7 @@ namespace App\Controllers; use CodeIgniter\API\ResponseTrait; use CodeIgniter\Controller; use \Firebase\JWT\JWT; +use CodeIgniter\Cookie\Cookie; class Auth extends Controller { use ResponseTrait; @@ -13,7 +14,52 @@ class Auth extends Controller { $this->db = \Config\Database::connect(); } + // public function login() { + // $username = $this->request->getVar('username'); + // $password = $this->request->getVar('password'); + // $key = getenv('JWT_SECRET'); + + // if (!$username) { + // return $this->fail('Username required.', 400); + // } + + // $sql = "SELECT * FROM users WHERE username=".$this->db->escape($username); + // $query = $this->db->query($sql); + // $row = $query->getRowArray(); + + // if (!$row) { + // return $this->fail('User not found.', 401); // Use 401 for authentication failures + // } + + // if (!password_verify($password, $row['password'])) { + // return $this->fail('Invalid password.', 401); + // } + + // // JWT payload + // $payload = [ + // 'userid' => $row['id'], + // 'username' => $row['username'], + // 'exp' => time() + 3600 + // ]; + + // try { + // $jwt = JWT::encode($payload, $key, 'HS256'); + // } catch (Exception $e) { + // return $this->fail('Error generating JWT: ' . $e->getMessage(), 500); + // } + + // // Update last_login + // //$this->userModel->update($user['id'], ['lastlogin' => date('Y-m-d H:i:s')]); + + // $response = [ + // 'status' => 'success', + // 'message' => 'Login successful', + // 'token' => $jwt, + // ]; + // return $this->respond($response); + // } public function login() { + $username = $this->request->getVar('username'); $password = $this->request->getVar('password'); $key = getenv('JWT_SECRET'); @@ -21,23 +67,24 @@ class Auth extends Controller { if (!$username) { return $this->fail('Username required.', 400); } - - $sql = "select * from users where username=".$this->db->escape($username); + + $sql = "SELECT * FROM users WHERE username=" . $this->db->escape($username); $query = $this->db->query($sql); $row = $query->getRowArray(); if (!$row) { - return $this->fail('User not found.', 401); // Use 401 for authentication failures + return $this->fail('User not found.', 401); } - + if (!password_verify($password, $row['password'])) { return $this->fail('Invalid password.', 401); } - + // JWT payload $payload = [ + 'userid' => $row['id'], 'username' => $row['username'], - 'exp' => time() + 3600 + 'exp' => time() + 3600 ]; try { @@ -46,14 +93,23 @@ class Auth extends Controller { return $this->fail('Error generating JWT: ' . $e->getMessage(), 500); } - // Update last_login - //$this->userModel->update($user['id'], ['lastlogin' => date('Y-m-d H:i:s')]); + // Set cookie (HttpOnly + Secure + SameSite=Strict) + $this->response->setCookie([ + 'name' => 'token', + 'value' => $jwt, + 'expire' => 3600, // 1 jam + 'path' => '/', + 'secure' => true, // set true kalau sudah HTTPS + 'httponly' => true, + 'samesite' => Cookie::SAMESITE_NONE // set true kalau sudah HTTPS + // 'samesite' => Cookie::SAMESITE_STRICT + ]); - $response = [ - 'message' => 'Login successful', - 'token' => $jwt, - ]; - return $this->respond($response); + // Response tanpa token di body + return $this->respond([ + 'status' => 'success', + 'message' => 'Login successful' + ]); } public function change_pass() { @@ -78,58 +134,50 @@ class Auth extends Controller { } public function register() { + $username = $this->request->getJsonVar('username'); $password = $this->request->getJsonVar('password'); $password = password_hash($password, PASSWORD_DEFAULT); - $master = $this->request->getJsonVar('master'); - $masterkey = getenv('MASTERKEY'); + // $master = $this->request->getJsonVar('master'); + // $masterkey = getenv('MASTERKEY'); + + // if($master != $masterkey) { + // return $this->fail('Invalid master key.', 401); + // } - if($master != $masterkey) { - return $this->fail('Invalid master key.', 401); - } - - $sql = "insert into users(username, password) values('$username', '$password')"; + $sql = "INSERT INTO users(username, password) values('$username', '$password')"; $this->db->query($sql); $response = [ - 'message' => "user $username created" + 'message' => "User $username created" ]; return $this->respondCreated($response); } public function checkAuth() { - $authorizationHeader = $this->request->getHeader('Authorization'); + $token = $this->request->getCookie('token'); + $key = getenv('JWT_SECRET'); - if (!$authorizationHeader) { - return $this->fail('Authorization header is missing', 401); + if (!$token) { + return $this->fail('No token found', 401); } - $authHeaderValue = $authorizationHeader->getValue(); - - if (empty($authHeaderValue)) { - return $this->fail('Authorization header is empty', 401); - } - - // Extract the token from the "Bearer " format - if (strpos($authHeaderValue, 'Bearer ') === 0) { - $token = substr($authHeaderValue, 7); - } else { - $token = $authHeaderValue; // Assume the header contains only the token - } - - try { - $decoded = JWT::decode($token, $this->key, ['HS256']); // Use the Key object - // You can now access user data from $decoded - $response = [ - 'message' => 'Authentication successful', - 'user' => $decoded, // return the decoded token - ]; - return $this->respond($response); - - } catch (Exception $e) { - return $this->fail('Invalid token: ' . $e->getMessage(), 401); + $decoded = JWT::decode($token, new Key($key, 'HS256')); + return $this->respond([ + 'status' => 'success', + 'message' => 'Authenticated', + 'data' => $decoded + ]); + } catch (\Exception $e) { + return $this->fail('Invalid or expired token: ' . $e->getMessage(), 401); } } + public function logout() { + return $this->response + ->deleteCookie('token') + ->setJSON(['message' => 'Logout successful']); + } + } \ No newline at end of file diff --git a/app/Filters/Cors.php b/app/Filters/Cors.php index e989e43..c18b5aa 100644 --- a/app/Filters/Cors.php +++ b/app/Filters/Cors.php @@ -22,7 +22,8 @@ class Cors implements FilterInterface if (in_array($origin, $this->allowedOrigins)) { $response->setHeader('Access-Control-Allow-Origin', $origin); $response->setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS'); - $response->setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With'); + $response->setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, Origin, Cache-Control, Pragma'); + // $response->setHeader('Access-Control-Allow-Headers', '*'); $response->setHeader('Access-Control-Allow-Credentials', 'true'); }