From b81a840ffd83581c879c72099decbc0e321074fc Mon Sep 17 00:00:00 2001 From: Mahdi Date: Tue, 11 Aug 2026 19:53:40 +0330 Subject: [PATCH] fix(super): accept SMS shared secret as Bearer for kill-switch Co-authored-by: Cursor --- .../EnsureSuperAdminRemoteToken.php | 46 +++++++++++++------ 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/app/Http/Middleware/EnsureSuperAdminRemoteToken.php b/app/Http/Middleware/EnsureSuperAdminRemoteToken.php index cd6f599..8f68544 100644 --- a/app/Http/Middleware/EnsureSuperAdminRemoteToken.php +++ b/app/Http/Middleware/EnsureSuperAdminRemoteToken.php @@ -7,10 +7,9 @@ use Illuminate\Http\Request; /** * Auth for SuperAdmin → product (kill-switch / super settings): - * 1) Preferred: shared HMAC (same secret as SMS) - * X-Abshode-Domain, X-Abshode-Timestamp, X-Abshode-Signature - * payload = `{ts}.{METHOD}./api/super/settings.{domain}` - * 2) Fallback: Authorization Bearer {SUPERADMIN_REMOTE_TOKEN} + * 1) Authorization Bearer matching SUPERADMIN_REMOTE_TOKEN + * OR SUPERADMIN_SMS_SHARED_SECRET (CDN-safe; same secret as SMS) + * 2) Optional: shared HMAC headers X-Abshode-* (may be stripped by CDN) */ class EnsureSuperAdminRemoteToken { @@ -20,11 +19,11 @@ class EnsureSuperAdminRemoteToken public function handle(Request $request, Closure $next) { - if ($this->authByHmac($request)) { + if ($this->authByBearer($request)) { return $next($request); } - if ($this->authByBearer($request)) { + if ($this->authByHmac($request)) { return $next($request); } @@ -62,8 +61,7 @@ class EnsureSuperAdminRemoteToken } $domain = $this->normalizeHost($domainHeader); - $expectedDomain = $this->configuredDomain(); - if ($domain === '' || $expectedDomain === '' || ! hash_equals($expectedDomain, $domain)) { + if ($domain === '' || ! $this->domainAllowed($domain, $request)) { return false; } @@ -76,19 +74,39 @@ class EnsureSuperAdminRemoteToken private function authByBearer(Request $request): bool { - $expected = $this->bearerToken(); - if ($expected === '') { - return false; - } - $auth = (string) $request->header('Authorization', ''); if (! preg_match('/^\s*Bearer\s+(.+)\s*$/i', $auth, $m)) { return false; } $token = trim($m[1]); + if ($token === '') { + return false; + } - return $token !== '' && hash_equals($expected, $token); + foreach ([$this->bearerToken(), $this->sharedSecret()] as $expected) { + if ($expected !== '' && hash_equals($expected, $token)) { + return true; + } + } + + return false; + } + + private function domainAllowed(string $domain, Request $request): bool + { + $candidates = [ + $this->configuredDomain(), + $this->normalizeHost((string) $request->getHost()), + ]; + + foreach ($candidates as $candidate) { + if ($candidate !== '' && hash_equals($candidate, $domain)) { + return true; + } + } + + return false; } private function sharedSecret(): string