From 22a752d3f3451b950e71346ab11eae8983963105 Mon Sep 17 00:00:00 2001 From: Isaac Souza Date: Thu, 16 Nov 2023 14:53:56 -0300 Subject: [PATCH] Fix scopeOfKey when compatibility mode is on and keys are prefixed with ID --- src/Models/ApiKey.php | 39 +++++++++++++++++++++++++---- tests/Feature/CompatibilityMode.php | 18 ++++++++++--- 2 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/Models/ApiKey.php b/src/Models/ApiKey.php index 6e21107..405dbb5 100644 --- a/src/Models/ApiKey.php +++ b/src/Models/ApiKey.php @@ -105,17 +105,46 @@ public function scopeOfKey(Builder $query, string $key): Builder if ($compatibilityMode) { return $query->where(function (Builder $query) use ($key) { - return $query->where('key', $key) - ->orWhere('key', hash('sha256', $key)); + if ($this->isMissingId($key)) { + return $query->where('key', $key) + ->orWhere('key', hash('sha256', $key)); + } + + $id = $this->extractId($key); + $key = $this->extractKey($key); + + return $query + ->where(function (Builder $query) use ($key, $id) { + return $query->where('key', $key) + ->where('id', $id); + }) + ->orWhere(function (Builder $query) use ($key, $id) { + return $query->where('key', hash('sha256', $key)) + ->where('id', $id); + }); }); } - if (strpos($key, '|') === false) { + if ($this->isMissingId($key)) { return $query->where('key', hash('sha256', $key)); } - [$id, $key] = explode('|', $key, 2); + return $query->where('id', $this->extractId($key)) + ->where('key', hash('sha256', $this->extractKey($key))); + } + + private function isMissingId(string $key): bool + { + return strpos($key, '|') === false; + } - return $query->where('id', $id)->where('key', hash('sha256', $key)); + private function extractId(string $key): string + { + return explode('|', $key, 2)[0]; + } + + private function extractKey(string $key): string + { + return explode('|', $key, 2)[1]; } } diff --git a/tests/Feature/CompatibilityMode.php b/tests/Feature/CompatibilityMode.php index 714f7e4..cc51604 100644 --- a/tests/Feature/CompatibilityMode.php +++ b/tests/Feature/CompatibilityMode.php @@ -71,14 +71,24 @@ public function accepts_both_hashed_and_non_hashed_api_keys_when_compatibility_m 'key' => $apiKey2->fresh()->key, ]); - // Assert the non hashed api keys works + // Assert that non hashed api keys works $this->withHeaders([ - 'Authorization' => 'Bearer ' . $plainTextApiKey1, + 'Authorization' => "Bearer {$plainTextApiKey1}", ])->get("/api/posts/{$post->id}")->assertOk(); - // Assert the hashed api keys works + // Assert that non hashed api keys with ID prefix works $this->withHeaders([ - 'Authorization' => 'Bearer ' . $plainTextApiKey2, + 'Authorization' => "Bearer {$apiKey1->id}|{$plainTextApiKey1}", + ])->get("/api/posts/{$post->id}")->assertOk(); + + // Assert that hashed api keys works + $this->withHeaders([ + 'Authorization' => "Bearer {$plainTextApiKey2}", + ])->get("/api/posts/{$post->id}")->assertOk(); + + // Assert that hashed api keys with ID prefix works + $this->withHeaders([ + 'Authorization' => "Bearer {$apiKey2->id}|{$plainTextApiKey2}", ])->get("/api/posts/{$post->id}")->assertOk(); } }