false, 'error' => 'API 서버 URL이 설정되지 않았습니다.']; } if (empty($exchangeSecret)) { Log::error('[ApiTokenService] Exchange secret not configured'); return ['success' => false, 'error' => '토큰 교환 비밀키가 설정되지 않았습니다.']; } // 만료 시간 계산 (현재 시간 + 유효 시간) $exp = time() + self::SIGNATURE_VALID_DURATION; // HMAC 서명 생성 $payload = "{$userId}:{$tenantId}:{$exp}"; $signature = hash_hmac('sha256', $payload, $exchangeSecret); try { $response = Http::timeout(10) ->post("{$baseUrl}/api/v1/internal/exchange-token", [ 'user_id' => $userId, 'tenant_id' => $tenantId, 'exp' => $exp, 'signature' => $signature, ]); if ($response->successful()) { $data = $response->json('data'); Log::info('[ApiTokenService] Token exchanged successfully', [ 'user_id' => $userId, 'tenant_id' => $tenantId, ]); return [ 'success' => true, 'data' => [ 'access_token' => $data['access_token'], 'token_type' => $data['token_type'] ?? 'Bearer', 'expires_in' => $data['expires_in'] ?? 3600, ], ]; } $error = $response->json('message') ?? '토큰 교환에 실패했습니다.'; Log::warning('[ApiTokenService] Token exchange failed', [ 'user_id' => $userId, 'tenant_id' => $tenantId, 'status' => $response->status(), 'error' => $error, ]); return ['success' => false, 'error' => $error]; } catch (\Exception $e) { Log::error('[ApiTokenService] Token exchange exception', [ 'user_id' => $userId, 'tenant_id' => $tenantId, 'exception' => $e->getMessage(), ]); return ['success' => false, 'error' => 'API 서버 연결에 실패했습니다.']; } } /** * 세션에 저장된 API 토큰 조회 */ public function getSessionToken(): ?string { return session('api_access_token'); } /** * API 토큰을 세션에 저장 * * @param string $token Bearer 토큰 * @param int $expiresIn 만료 시간 (초) */ public function storeTokenInSession(string $token, int $expiresIn): void { session([ 'api_access_token' => $token, 'api_token_expires_at' => now()->addSeconds($expiresIn)->timestamp, ]); } /** * 세션의 API 토큰 삭제 */ public function clearSessionToken(): void { session()->forget(['api_access_token', 'api_token_expires_at']); } /** * 토큰이 만료되었는지 확인 */ public function isTokenExpired(): bool { $expiresAt = session('api_token_expires_at'); if (! $expiresAt) { return true; } // 5분 전에 미리 갱신하도록 (버퍼) return time() > ($expiresAt - 300); } }