fix(super): accept SMS shared secret as Bearer for kill-switch
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user