From abeef421b566b0acdaa8904c8c0751368ff4ad68 Mon Sep 17 00:00:00 2001 From: Marcel Pociot Date: Thu, 22 Nov 2018 21:36:25 +0100 Subject: [PATCH] wip --- composer.json | 1 + .../Http/Controllers/EchoController.php | 36 ++++++++++--- .../Http/Controllers/FetchChannel.php | 54 +++++++++++++++++++ .../{EventController.php => TriggerEvent.php} | 8 +-- src/Router.php | 4 +- 5 files changed, 91 insertions(+), 12 deletions(-) create mode 100644 src/LaravelEcho/Http/Controllers/FetchChannel.php rename src/LaravelEcho/Http/Controllers/{EventController.php => TriggerEvent.php} (89%) diff --git a/composer.json b/composer.json index 3722235..d80f32c 100644 --- a/composer.json +++ b/composer.json @@ -29,6 +29,7 @@ "illuminate/http": "5.6.*|5.7.*", "illuminate/routing": "5.6.*|5.7.*", "illuminate/support": "5.6.*|5.7.*", + "symfony/http-kernel": "~4.0", "symfony/psr-http-message-bridge": "^1.1" }, "require-dev": { diff --git a/src/LaravelEcho/Http/Controllers/EchoController.php b/src/LaravelEcho/Http/Controllers/EchoController.php index 4123ee8..67bf27c 100644 --- a/src/LaravelEcho/Http/Controllers/EchoController.php +++ b/src/LaravelEcho/Http/Controllers/EchoController.php @@ -2,17 +2,21 @@ namespace BeyondCode\LaravelWebSockets\LaravelEcho\Http\Controllers; +use Exception; use Illuminate\Http\Request; +use GuzzleHttp\Psr7 as gPsr; +use GuzzleHttp\Psr7\Response; use Ratchet\ConnectionInterface; use Illuminate\Http\JsonResponse; use GuzzleHttp\Psr7\ServerRequest; use Ratchet\Http\HttpServerInterface; use Psr\Http\Message\RequestInterface; +use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Bridge\PsrHttpMessage\Factory\HttpFoundationFactory; abstract class EchoController implements HttpServerInterface { - public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) + public function onOpen(ConnectionInterface $connection, RequestInterface $request = null) { $queryParameters = []; parse_str($request->getUri()->getQuery(), $queryParameters); @@ -25,22 +29,42 @@ abstract class EchoController implements HttpServerInterface $request->getProtocolVersion() ))->withQueryParams($queryParameters); - $response = $this(Request::createFromBase((new HttpFoundationFactory)->createRequest($serverRequest))); - $conn->send(JsonResponse::create($response)->send()); - $conn->close(); + $laravelRequest = Request::createFromBase((new HttpFoundationFactory)->createRequest($serverRequest)); + + // Always verify the app id + $this->verifyAppId($laravelRequest->appId); + + $response = $this($laravelRequest); + + $connection->send(JsonResponse::create($response)->send()); + $connection->close(); } function onMessage(ConnectionInterface $from, $msg) { } - function onClose(ConnectionInterface $conn) + function onClose(ConnectionInterface $connection) { } - function onError(ConnectionInterface $conn, \Exception $e) + function onError(ConnectionInterface $connection, Exception $exception) { + if ($exception instanceof HttpException) + { + $response = new Response($exception->getStatusCode(), $exception->getHeaders(), $exception->getMessage()); + + $connection->send(gPsr\str($response)); + $connection->close(); + } + } + + public function verifyAppId(string $appId) + { + if ($appId !== config('broadcasting.connections.pusher.app_id')) { + throw new HttpException(401, 'Invalid App ID provided.'); + } } abstract public function __invoke(Request $request); diff --git a/src/LaravelEcho/Http/Controllers/FetchChannel.php b/src/LaravelEcho/Http/Controllers/FetchChannel.php new file mode 100644 index 0000000..5cae807 --- /dev/null +++ b/src/LaravelEcho/Http/Controllers/FetchChannel.php @@ -0,0 +1,54 @@ +channelManager = $channelManager; + } + + public function __invoke(Request $request) + { + $this->verifySignature($request); + + foreach ($request->json()->get('channels', []) as $channelId) { + $channel = $this->channelManager->find($request->appId, $channelId); + + optional($channel)->broadcast([ + 'channel' => $channelId, + 'event' => $request->json()->get('name'), + 'data' => $request->json()->get('data'), + ]); + } + + return $request->json()->all(); + } + + protected function verifySignature(Request $request) + { + $bodyMd5 = md5($request->getContent()); + + $signature = + "POST\n/apps/{$request->appId}/events\n". + "auth_key={$request->auth_key}". + "&auth_timestamp={$request->auth_timestamp}". + "&auth_version={$request->auth_version}". + "&body_md5={$bodyMd5}"; + + $authSignature = hash_hmac('sha256', $signature, config('broadcasting.connections.pusher.secret')); + + if ($authSignature !== $request->get('auth_signature')) { + throw new HttpException(401, 'Invalid authentication signature.'); + } + } +} \ No newline at end of file diff --git a/src/LaravelEcho/Http/Controllers/EventController.php b/src/LaravelEcho/Http/Controllers/TriggerEvent.php similarity index 89% rename from src/LaravelEcho/Http/Controllers/EventController.php rename to src/LaravelEcho/Http/Controllers/TriggerEvent.php index dc187c8..34c421b 100644 --- a/src/LaravelEcho/Http/Controllers/EventController.php +++ b/src/LaravelEcho/Http/Controllers/TriggerEvent.php @@ -2,11 +2,11 @@ namespace BeyondCode\LaravelWebSockets\LaravelEcho\Http\Controllers; -use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager; -use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Exceptions\InvalidSignatureException; use Illuminate\Http\Request; +use Symfony\Component\HttpKernel\Exception\HttpException; +use BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager; -class EventController extends EchoController +class TriggerEvent extends EchoController { /** @var \BeyondCode\LaravelWebSockets\LaravelEcho\Pusher\Channels\ChannelManager */ protected $channelManager; @@ -47,7 +47,7 @@ class EventController extends EchoController $authSignature = hash_hmac('sha256', $signature, config('broadcasting.connections.pusher.secret')); if ($authSignature !== $request->get('auth_signature')) { - throw new InvalidSignatureException(); + throw new HttpException(401, 'Invalid auth signature provided.'); } } } \ No newline at end of file diff --git a/src/Router.php b/src/Router.php index 2e0342a..a2f2150 100644 --- a/src/Router.php +++ b/src/Router.php @@ -71,10 +71,10 @@ class Router // TODO: fleshen out http API $this->get('/apps/{appId}/status', LaravelEcho\Http\Controllers\StatusController::class); $this->get('/apps/{appId}/channels', LaravelEcho\Http\Controllers\StatusController::class); - $this->get('/apps/{appId}/channels/{channelName}', LaravelEcho\Http\Controllers\StatusController::class); + $this->get('/apps/{appId}/channels/{channelName}', LaravelEcho\Http\Controllers\FetchChannel::class); $this->get('/apps/{appId}/channels/{channelName}/users', LaravelEcho\Http\Controllers\StatusController::class); - $this->post('/apps/{appId}/events', LaravelEcho\Http\Controllers\EventController::class); + $this->post('/apps/{appId}/events', LaravelEcho\Http\Controllers\TriggerEvent::class); } /**