authByHmac($request)) { return $next($request); } if ($this->authByBearer($request)) { return $next($request); } $hasSecret = $this->sharedSecret() !== ''; $hasToken = $this->bearerToken() !== ''; if (! $hasSecret && ! $hasToken) { return response()->json([ 'message' => 'SUPERADMIN_SMS_SHARED_SECRET or SUPERADMIN_REMOTE_TOKEN is not configured', ], 503); } return response()->json(['message' => 'Unauthorized'], 401); } private function authByHmac(Request $request): bool { $secret = $this->sharedSecret(); if ($secret === '') { return false; } $domainHeader = trim((string) $request->header('X-Abshode-Domain', '')); $tsRaw = trim((string) $request->header('X-Abshode-Timestamp', '')); $sigRaw = trim((string) $request->header('X-Abshode-Signature', '')); if ($domainHeader === '' || $tsRaw === '' || $sigRaw === '') { return false; } if (! ctype_digit($tsRaw)) { return false; } $timestamp = (int) $tsRaw; if (abs(time() - $timestamp) > self::MAX_SKEW_SECONDS) { return false; } $domain = $this->normalizeHost($domainHeader); $expectedDomain = $this->configuredDomain(); if ($domain === '' || $expectedDomain === '' || ! hash_equals($expectedDomain, $domain)) { return false; } $method = strtoupper($request->getMethod()); $payload = $timestamp.'.'.$method.'.'.self::CANONICAL_PATH.'.'.$domain; $expected = hash_hmac('sha256', $payload, $secret); return hash_equals(strtolower($expected), strtolower($sigRaw)); } 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]); return $token !== '' && hash_equals($expected, $token); } private function sharedSecret(): string { return trim((string) config('services.superadmin.sms_shared_secret', '')); } private function bearerToken(): string { return trim((string) config('services.superadmin.remote_token', '')); } private function configuredDomain(): string { $override = trim((string) config('services.superadmin.sms_domain', '')); if ($override !== '') { return $this->normalizeHost($override); } $fromApp = parse_url((string) config('app.url'), PHP_URL_HOST); return $this->normalizeHost(is_string($fromApp) ? $fromApp : ''); } private function normalizeHost(string $value): string { $host = strtolower(trim($value)); $host = preg_replace('#^https?://#', '', $host) ?? $host; $host = explode('/', $host)[0] ?? $host; $host = explode(':', $host)[0] ?? $host; return trim($host); } }