- Extend `users_o` and `subusers_o` with `two_factor_enabled` and `two_factor_secret` properties. - Implement methods for managing 2FA (`isTwoFactorEnabled`, `setTwoFactorSecret`, `verify_2fa_code`) in authentication logic. - Add 2FA handling in login flows for both users and subusers, including token generation and validation. - Introduce `totp` class for TOTP-based authentication, including QR code generation and code verification. - Add test cases for 2FA functionality (`TwoFactorAuthTest.php`) and coverage for login scenarios with 2FA. - Update OpenAPI specifications to include 2FA flows (`auth/2fa/setup`, `auth/2fa/enable`, `auth/2fa/verify`, `auth/2fa/disable`).
65 lines
2.5 KiB
PHP
65 lines
2.5 KiB
PHP
<?php
|
|
|
|
if (!defined('WD')) {
|
|
define('WD', dirname(__DIR__, 2));
|
|
}
|
|
|
|
$_ENV['USE_ENV'] = 'true';
|
|
require_once WD . '/config.php';
|
|
require_once WD . '/classes/db.php';
|
|
require_once WD . '/classes/totp.php';
|
|
use classes\totp;
|
|
|
|
global $CONFIG_DB;
|
|
$db = new \classes\db($CONFIG_DB);
|
|
$db->connect();
|
|
|
|
function assert_true($condition, $message)
|
|
{
|
|
if ($condition) {
|
|
echo "✔ $message\n";
|
|
} else {
|
|
echo "✘ $message\n";
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
echo "Testing TOTP class...\n";
|
|
$totp = new totp();
|
|
$secret = $totp->generateSecret();
|
|
assert_true(strlen($secret) === 16, "Secret length is 16");
|
|
$code = $totp->getCode($secret);
|
|
assert_true(strlen($code) === 6, "Code length is 6");
|
|
assert_true($totp->verifyCode($secret, $code), "Verify current code");
|
|
assert_true(!$totp->verifyCode($secret, '000000'), "Reject invalid code");
|
|
|
|
echo "\nTesting 2FA columns on users table...\n";
|
|
$colCheck = $db->query("SELECT COUNT(*) AS cnt FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '".$CONFIG_DB['database']."' AND TABLE_NAME = 'users' AND COLUMN_NAME IN ('two_factor_secret','two_factor_enabled')");
|
|
$row = $db->fetch_assoc($colCheck);
|
|
assert_true((int)$row['cnt'] >= 2, "Users table has 2FA columns");
|
|
|
|
$setup_secret = $totp->generateSecret();
|
|
$valid_code = $totp->getCode($setup_secret);
|
|
assert_true($totp->verifyCode($setup_secret, $valid_code), "Verify code for generated secret");
|
|
|
|
echo "\nTesting 2FA for Subuser (Driver) via DB...\n";
|
|
$test_subuser_id = 999999;
|
|
$db->query("DELETE FROM subusers WHERE id = $test_subuser_id");
|
|
$pwd = password_hash('password123', PASSWORD_DEFAULT);
|
|
$db->query("INSERT INTO subusers (id, username, password, name, email, phone_country_code, phone) VALUES ($test_subuser_id, 'testdriver', '$pwd', 'Test Driver', 'driver@example.com', 45, 20123456)");
|
|
|
|
$sub_secret = $totp->generateSecret();
|
|
$sub_code = $totp->getCode($sub_secret);
|
|
assert_true($totp->verifyCode($sub_secret, $sub_code), "TOTP verifies subuser code");
|
|
|
|
$db->query("UPDATE subusers SET two_factor_secret = '$sub_secret', two_factor_enabled = 1 WHERE id = $test_subuser_id");
|
|
$res = $db->query("SELECT two_factor_enabled, two_factor_secret FROM subusers WHERE id = $test_subuser_id");
|
|
$row = $db->fetch_assoc($res);
|
|
assert_true((int)$row['two_factor_enabled'] === 1, "Subuser 2FA enabled flag persisted");
|
|
assert_true($row['two_factor_secret'] === $sub_secret, "Subuser secret persisted");
|
|
|
|
// Cleanup
|
|
$db->query("DELETE FROM subusers WHERE id = $test_subuser_id");
|
|
|
|
echo "\nTwoFactorAuthTest completed successfully!\n";
|