clientRepository = $clientRepository; } /** * Xác thực khách hàng và tạo access + refresh token */ public function authenticateClient(array $credentials): array { if (!$token = Auth::guard('client')->attempt($credentials)) { throw ValidationException::withMessages([ 'email' => ['Thông tin đăng nhập không chính xác.'], ]); } $client = Auth::guard('client')->user(); if ((int)$client->status !== 1) { $statusLabel = match ((int)$client->status) { 0 => 'chờ xác thực', 2 => 'tạm ngưng hoạt động', 3 => 'bị khoá', default => 'vô hiệu hoá', }; throw ValidationException::withMessages([ 'email' => ["Tài khoản của bạn đã {$statusLabel}, vui lòng liên hệ hotline."], ]); } $refreshToken = $this->createRefreshToken($client->id); return [ 'client' => $client, 'token' => $token, 'refresh_token' => $refreshToken, ]; } /** * Đăng ký khách hàng mới và tạo access + refresh token */ public function registerClient(array $data): array { $client = $this->clientRepository->create([ 'fullname' => $data['fullname'], 'phone' => $data['phone'], 'email' => $data['email'], 'password' => bcrypt($data['password']), ]); $token = JWTAuth::fromUser($client); $refreshToken = $this->createRefreshToken($client->id); return [ 'client' => $client, 'token' => $token, 'refresh_token' => $refreshToken, ]; } /** * Tạo refresh token mới, lưu hash vào DB, trả về raw token. */ public function createRefreshToken(int $customerId): string { $raw = Str::random(64); $hash = hash('sha256', $raw); RefreshToken::create([ 'customer_id' => $customerId, 'token' => $hash, 'expires_at' => now()->addDays(self::REFRESH_TOKEN_TTL_DAYS), ]); return $raw; } /** * Xác minh refresh token, xoay vòng (rotation), trả về access token mới + refresh token mới. * Ném ValidationException nếu token không hợp lệ hoặc đã hết hạn. */ public function rotateRefreshToken(string $rawToken): array { $hash = hash('sha256', $rawToken); $record = RefreshToken::where('token', $hash)->first(); if (!$record || $record->isExpired()) { // Xoá token cũ nếu tồn tại nhưng hết hạn $record?->delete(); throw ValidationException::withMessages([ 'refresh_token' => ['Refresh token không hợp lệ hoặc đã hết hạn.'], ]); } $customer = $record->customer; if (!$customer || (int)$customer->status !== 1) { $record->delete(); throw ValidationException::withMessages([ 'refresh_token' => ['Tài khoản không hợp lệ.'], ]); } // Rotation: xoá token cũ $record->delete(); // Tạo access token mới $newAccessToken = JWTAuth::fromUser($customer); // Tạo refresh token mới $newRefreshToken = $this->createRefreshToken($customer->id); return [ 'client' => $customer, 'token' => $newAccessToken, 'refresh_token' => $newRefreshToken, ]; } /** * Huỷ refresh token khi đăng xuất. */ public function revokeRefreshToken(string $rawToken): void { $hash = hash('sha256', $rawToken); RefreshToken::where('token', $hash)->delete(); } }