From cf80e1fcaec925f5ea54c4a7e75ec4864254c994 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Tue, 19 May 2026 09:21:43 -0300 Subject: [PATCH] refactor(social): single source of truth for token redaction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same shape of bug as the refreshToken duplication: the regex that strips access_token / Bearer headers from logged HTTP bodies existed in three near-identical copies (HasSocialHttpClient trait, TokenRefreshClient, SocialPublishException), drifting subtly — SocialPublishException was missing the JSON "token" pattern. Extracts a TokenRedactor::redact(string) helper and routes all callers through it. Adding a new token format now means one regex in one file. --- .../Social/SocialPublishException.php | 25 ++------------ .../Social/Concerns/HasSocialHttpClient.php | 17 ++-------- app/Services/Social/TokenRedactor.php | 33 +++++++++++++++++++ app/Services/Social/TokenRefreshClient.php | 21 +----------- 4 files changed, 38 insertions(+), 58 deletions(-) create mode 100644 app/Services/Social/TokenRedactor.php diff --git a/app/Exceptions/Social/SocialPublishException.php b/app/Exceptions/Social/SocialPublishException.php index 384695e6..8d007728 100644 --- a/app/Exceptions/Social/SocialPublishException.php +++ b/app/Exceptions/Social/SocialPublishException.php @@ -4,6 +4,7 @@ namespace App\Exceptions\Social; +use App\Services\Social\TokenRedactor; use RuntimeException; abstract class SocialPublishException extends RuntimeException @@ -27,32 +28,10 @@ public function context(): array 'category' => $this->category->value, 'platform_error_code' => $this->platformErrorCode, 'user_message' => $this->userMessage, - 'raw_response' => $this->redactTokens($this->rawResponse), + 'raw_response' => $this->rawResponse !== null ? TokenRedactor::redact($this->rawResponse) : null, ]; } - private function redactTokens(?string $text): ?string - { - if ($text === null) { - return null; - } - - // Redact common token patterns from API error responses - return preg_replace( - [ - '/access_token=([^&"\s]+)/', - '/"access_token"\s*:\s*"([^"]+)"/', - '/Bearer\s+\S+/', - ], - [ - 'access_token=[REDACTED]', - '"access_token":"[REDACTED]"', - 'Bearer [REDACTED]', - ], - $text - ); - } - abstract public static function fromApiResponse(mixed $response): static; abstract public function platform(): string; diff --git a/app/Services/Social/Concerns/HasSocialHttpClient.php b/app/Services/Social/Concerns/HasSocialHttpClient.php index 1aa41c7c..092ca717 100644 --- a/app/Services/Social/Concerns/HasSocialHttpClient.php +++ b/app/Services/Social/Concerns/HasSocialHttpClient.php @@ -5,6 +5,7 @@ namespace App\Services\Social\Concerns; use App\Models\PostPlatform; +use App\Services\Social\TokenRedactor; use Illuminate\Http\Client\PendingRequest; use Illuminate\Support\Facades\Http; @@ -38,20 +39,6 @@ protected function socialHttp(): PendingRequest protected function redactResponseBody(string $body): string { - return preg_replace( - [ - '/access_token=([^&"\s]+)/', - '/"access_token"\s*:\s*"([^"]+)"/', - '/Bearer\s+\S+/', - '/"token"\s*:\s*"([^"]+)"/', - ], - [ - 'access_token=[REDACTED]', - '"access_token":"[REDACTED]"', - 'Bearer [REDACTED]', - '"token":"[REDACTED]"', - ], - $body - ); + return TokenRedactor::redact($body); } } diff --git a/app/Services/Social/TokenRedactor.php b/app/Services/Social/TokenRedactor.php new file mode 100644 index 00000000..bc154048 --- /dev/null +++ b/app/Services/Social/TokenRedactor.php @@ -0,0 +1,33 @@ +failed()) { Log::error("TokenRefreshClient: {$name} token refresh failed", [ - 'body' => $this->redactBody($response->body()), + 'body' => TokenRedactor::redact($response->body()), ]); $body = $response->json(); @@ -71,23 +71,4 @@ public function send(Closure $request): Response return $response; } - - private function redactBody(string $body): string - { - return preg_replace( - [ - '/access_token=([^&"\s]+)/', - '/"access_token"\s*:\s*"([^"]+)"/', - '/Bearer\s+\S+/', - '/"token"\s*:\s*"([^"]+)"/', - ], - [ - 'access_token=[REDACTED]', - '"access_token":"[REDACTED]"', - 'Bearer [REDACTED]', - '"token":"[REDACTED]"', - ], - $body - ); - } }