configuration = $configuration; } public function handle(RequestInterface $request, ?WebSocket $proxyConnection): ?RequestInterface { if (! $this->requiresAuthentication() || is_null($proxyConnection)) { return $request; } $username = $this->getAuthorizationUsername($request); if (is_null($username)) { $proxyConnection->send( str(new \GuzzleHttp\Psr7\Response(401, [ 'WWW-Authenticate' => 'Basic realm=Expose' ], 'Unauthorized')) ); $proxyConnection->close(); return null; } return $request; } protected function getAuthorizationUsername(RequestInterface $request): ?string { $authorization = $this->parseAuthorizationHeader(Arr::get($request->getHeaders(), 'authorization.0', '')); $credentials = $this->getCredentials(); if (empty($authorization)) { return null; } if (!array_key_exists($authorization['username'], $credentials)) { return null; } if ($credentials[$authorization['username']] !== $authorization['password']) { return null; } return $authorization['username']; } protected function parseAuthorizationHeader(string $header) { if (strpos($header, 'Basic') !== 0) { return null; } $header = base64_decode(substr($header, 6)); if ($header === false) { return null; } $header = explode(':', $header, 2); return [ 'username' => $header[0], 'password' => isset($header[1]) ? $header[1] : null, ]; } protected function requiresAuthentication(): bool { return !empty($this->getCredentials()); } protected function getCredentials() { try { $credentials = explode(':', $this->configuration->auth()); return [ $credentials[0] => $credentials[1], ]; } catch (\Exception $e) { return []; } } }