Files
portal-api/app/Services/Api/Admin/AdminRefreshTokenService.php
baodev0 0b08689ea4 feat: harden admin auth and ticket workflows
- add rotating admin refresh tokens and password gates\n- expand ticket galleries, exports, and client resources\n- improve IP allocation auditing and dashboard data\n- enforce encrypted client access tokens on public routes
2026-10-16 17:00:55 +07:00

69 lines
2.0 KiB
PHP

<?php
namespace App\Services\Api\Admin;
use App\Models\AdminRefreshToken;
use Carbon\CarbonInterface;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Tymon\JWTAuth\Facades\JWTAuth;
class AdminRefreshTokenService
{
public function create(int $userId, CarbonInterface $expiresAt): string
{
$rawToken = Str::random(64);
AdminRefreshToken::create([
'user_id' => $userId,
'token' => hash('sha256', $rawToken),
'expires_at' => $expiresAt,
]);
return $rawToken;
}
public function rotate(string $rawToken): array
{
return DB::transaction(function () use ($rawToken): array {
$record = AdminRefreshToken::where('token', hash('sha256', $rawToken))
->lockForUpdate()
->first();
if (! $record || $record->expires_at->isPast()) {
$record?->delete();
throw ValidationException::withMessages([
'refresh_token' => ['Refresh token không hợp lệ hoặc đã hết hạn.'],
]);
}
$user = $record->user;
if (! $user) {
$record->delete();
throw ValidationException::withMessages([
'refresh_token' => ['Tài khoản không hợp lệ.'],
]);
}
$expiresAt = $record->expires_at->copy();
$record->delete();
$newRefreshToken = $this->create($user->id, $expiresAt);
return [
'user' => $user,
'token' => JWTAuth::fromUser($user),
'refresh_token' => $newRefreshToken,
'refresh_expires_in' => (int) max(0, now()->diffInSeconds($expiresAt, false)),
];
});
}
public function revoke(string $rawToken): void
{
AdminRefreshToken::where('token', hash('sha256', $rawToken))->delete();
}
}