Refactor passkey and token processing for improved consistency and validation
- Update passkey data mapping to use associative arrays and handle JSON decoding for `transports`. - Refactor token caching logic to validate database existence and clear stale entries. - Improve 2FA handling by centralizing `token->type` and `user_id` processing for reuse.
This commit is contained in:
@@ -23,7 +23,15 @@ class tokens_o extends db
|
||||
public function objectChanged(): void
|
||||
{
|
||||
// Invalidate the cache
|
||||
redis->clear_token($this->token->value());
|
||||
if ($this->id > 0) {
|
||||
try {
|
||||
$token = $this->token->value();
|
||||
redis->clear_token($token);
|
||||
} catch (\Exception $e) {
|
||||
// If the record is already gone or token cannot be retrieved, we can't clear by token string.
|
||||
// This can happen during a hard delete where objectChanged is called after the record is deleted.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function create(int $user_id, string $token, string $type = 'AUTH_TOKEN'): void
|
||||
@@ -58,9 +66,14 @@ class tokens_o extends db
|
||||
// Check if the token is cached
|
||||
$cached = redis->get_token($token);
|
||||
if ($cached) {
|
||||
$this->id = $cached['id'];
|
||||
$this->getObjectProperties();
|
||||
return $this;
|
||||
$this->id = (int)$cached['id'];
|
||||
// Verify that the token still exists in the database to avoid stale cache issues.
|
||||
if ($this->exists()) {
|
||||
$this->getObjectProperties();
|
||||
return $this;
|
||||
}
|
||||
// If it doesn't exist, clear the stale cache entry and proceed to check the database.
|
||||
redis->clear_token($token);
|
||||
}
|
||||
// Avoid SQL injection
|
||||
$token = $db->escape_string($token);
|
||||
|
||||
@@ -189,15 +189,18 @@ class authRoute
|
||||
}
|
||||
|
||||
$auth = new authentication();
|
||||
if ($token->type->value() === '2FA_VERIFICATION_USER') {
|
||||
$user = (new users_o())->getUserById($token->user_id->value());
|
||||
$token_type = $token->type->value();
|
||||
$user_id = (int)$token->user_id->value();
|
||||
|
||||
if ($token_type === '2FA_VERIFICATION_USER') {
|
||||
$user = (new users_o())->getUserById($user_id);
|
||||
if ($user->exists() && $auth->verify_2fa_code($user, $code)) {
|
||||
$token_o->delete($token_str);
|
||||
$new_token = $auth->create_employee_token($token->user_id->value()); // Works for both users and employees
|
||||
$new_token = $auth->create_employee_token($user_id); // Works for both users and employees
|
||||
$response->success(['token' => $new_token]);
|
||||
}
|
||||
} elseif ($token->type->value() === '2FA_VERIFICATION_SUBUSER') {
|
||||
$subuser = (new subusers_o())->select($token->user_id->value());
|
||||
} elseif ($token_type === '2FA_VERIFICATION_SUBUSER') {
|
||||
$subuser = (new subusers_o())->select($user_id);
|
||||
if ($auth->verify_2fa_code($subuser, $code)) {
|
||||
$token_o->delete($token_str);
|
||||
$new_token = $subuser->generateSession();
|
||||
|
||||
@@ -25,17 +25,23 @@ class passkeysRoute
|
||||
|
||||
$passkeys = new passkeys_o();
|
||||
// Restrict to current user (customer) and non-subuser records
|
||||
$passkeys->setAdditionalWhereClause('WHERE user_id = ' . (int)$user->id . ' AND is_subuser = 0 AND deleted_at IS NULL');
|
||||
$list = $passkeys->listObjects(function ($o) {
|
||||
$passkeys->setAdditionalWhereClause('`user_id` = ' . (int)$user->id . ' AND `is_subuser` = 0');
|
||||
$list = $passkeys->listObjectsWithPaginationIfSet(function ($o) {
|
||||
// $o is an associative array from the database
|
||||
$transports = null;
|
||||
if (isset($o['transports'])) {
|
||||
$decoded = json_decode($o['transports'], true);
|
||||
$transports = is_array($decoded) ? $decoded : null;
|
||||
}
|
||||
return [
|
||||
'id' => $o->id,
|
||||
'credential_id' => $o->credential_id->value(),
|
||||
'name' => $o->name->value(),
|
||||
'algorithm' => $o->algorithm->value(),
|
||||
'transports' => $o->transports->value(),
|
||||
'sign_count' => $o->sign_count->value(),
|
||||
'created_at' => $o->created_at->value(),
|
||||
'updated_at' => $o->updated_at->value(),
|
||||
'id' => isset($o['id']) ? (int)$o['id'] : null,
|
||||
'credential_id' => $o['credential_id'] ?? null,
|
||||
'name' => $o['name'] ?? null,
|
||||
'algorithm' => $o['algorithm'] ?? null,
|
||||
'transports' => $transports,
|
||||
'sign_count' => isset($o['sign_count']) ? (int)$o['sign_count'] : null,
|
||||
'created_at' => $o['created_at'] ?? null,
|
||||
'updated_at' => $o['updated_at'] ?? null,
|
||||
];
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user