Laravel Websockets raises a BroadcastException "Invalid auth signature provided" - php

I'm trying to add websockets support to my Laravel 9 application. I've read in their documentation that I could run an open source server on my own instead of relying on commercial solutions. With that in mind, I decided to give Beyondcode's Laravel Websockets a try. My application runs on PHP 8.2, using Laravel 9.19 and Laravel Websockets 1.13, communicating with the sockets through the Pusher Channels HTTP PHP Library 7.2.
Laravel Websockets is meant to match the server's settings with the client's by using the same naming scheme on both ends and launching off the same codebase.
This is how I've set up my .env file:
APP_NAME="My app"
APP_ENV=local
APP_KEY=<redacted>
APP_DEBUG=true
BROADCAST_DRIVER=pusher
PUSHER_APP_ID="${APP_NAME}"
PUSHER_APP_KEY="${APP_KEY}"
PUSHER_APP_SECRET="${APP_KEY}${APP_NAME}"
PUSHER_HOST=ws-server
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
My docker-compose.yml file contains the following content:
version: "3.9"
services:
queue:
build: .
environment:
- ROLE=queue
volumes:
- .:/var/www
ws-server:
build: .
environment:
- ROLE=ws-server
volumes:
- .:/var/www
ports:
- 6001:6001
The ws-server service has an entrypoint script which runs the following command on an infinite loop: php artisan websockets:serve --host 0.0.0.0 --port 6001
Within config/websockets.php I've left everything as it comes out of the box, just so you can rest assured, this is how my apps array looks like:
'apps' => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
]
The queue service hosts a class called TerminalUpdated, which looks like this:
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class TerminalUpdated implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public string $id;
public string $newLine;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(string $id, string $newLine)
{
$this->id = $id;
$this->newLine = $newLine;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('console.' . $this->id);
}
}
Another script running within the service mentioned above executes the following sentence:
<?php
$id = '123';
$line = 'This is a line of text.';
TerminalUpdated::dispatch(
$this->id, // id
$line // newLine
);
?>
Everything looks more or less okay to me, yet I'm getting the following exception:
[2023-01-19 01:05:09] local.ERROR: Pusher error: {"error":"Invalid auth signature provided."}. {"exception":"[object] (Illuminate\\Broadcasting\\BroadcastException(code: 0): Pusher error: {\"error\":\"Invalid auth signature provided.\"}. at /var/www/vendor/laravel/framework/src/Illuminate/Broadcasting/Broadcasters/PusherBroadcaster.php:164)
"}
I don't seem to be able to figure out where is it even trying to generate the signature mentioned in the exception shown above.
I've already tried the following possible fixes:
Restart the server
Reset the framework's caches and temporary files by calling php artisan optimize:clear

This is how I configured the WebSocket:
In the websocket.php file :
apps => [
[
'id' => env('PUSHER_APP_ID'),
'name' => env('APP_NAME'),
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'path' => env('PUSHER_APP_PATH'),
'capacity' => null,
'enable_client_messages' => false,
'enable_statistics' => true,
],
],
In broadcasting.php I have:
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => false,
'encrypted' => false,
'host'=> '127.0.0.1',
'port' => 6001,
'scheme' => 'http',
],
],
I hope it helps you out.

The problem is that PUSHER_APP_ID can't contain spaces. Using a string without spaces instead fixes the issue. It looks like the library just can't translate the spaces to the expected URL encoding.

Related

Sockets not working in AWS ec2 using PHP?

Unable to make socket.io working on AWS EC2
https://mydoamin.com:2120/socket.io/?EIO=3&transport=polling&t=NQpMyRI net::ERR_TIMED_OUT
i.create # socket.io.js?v=1609310849:7
Localhost everything working fine the way it should be working but on live environment, I am getting above error.
When I connect using [workerman][1] and starting it using CLI on was ubuntu instance it is working fine
Somehow ports are not working properly even I have added it in security groups under inbound settings:-
And now this error after configuring:
<?php
use kriss\webMsgSender\WebMsgSender;
return [
'components' => [
// others
WebMsgSender::COMPONENT_NAME => [
'class' => WebMsgSender::class,
'pushApiClientHost' => '0.0.0.0',
'logCategory' => 'webMsgSender',
],
],
];
New error
socket.io.js?v=1609310849:7 GET https://myDoamin.com:2120/socket.io/?EIO=3&transport=polling&t=NQpU3PA net::ERR_CONNECTION_RESET
Extension I am using
Make sure you configure socket io to listen to be bonded to all IP addresses, not just the localhost
so instead of
<?php
use kriss\webMsgSender\WebMsgSender;
return [
'components' => [
// others
WebMsgSender::COMPONENT_NAME => [
'class' => WebMsgSender::class,
'pushApiClientHost' => 'localhost',
'logCategory' => 'webMsgSender',
],
],
];
change to
<?php
use kriss\webMsgSender\WebMsgSender;
return [
'components' => [
// others
WebMsgSender::COMPONENT_NAME => [
'class' => WebMsgSender::class,
'pushApiClientHost' => '0.0.0.0',
'logCategory' => 'webMsgSender',
],
],
];
basically change localhost to 0.0.0.0

Exception: Illuminate \ Broadcasting \ BroadcastException No message in PusherBroadcaster.php:119

Laravel 5.8
I am new to this whole pusher functionality and I've been following this tutorial and trying it out,
Create Web Notifications Using Laravel and Pusher Channels.
I've followed it step-by-step and when I get to the step to manually test the event by visiting the test url, I receive the following exception:
Illuminate \ Broadcasting \ BroadcastException
No message
C:\wamp\www\ares\vendor\laravel\framework\src\Illuminate\Broadcasting\Broadcasters\PusherBroadcaster.php
Here is the code:
$response = $this->pusher->trigger(
$this->formatChannels($channels), $event, $payload, $socket, true
);
if ((is_array($response) && $response['status'] >= 200 && $response['status'] <= 299)
|| $response === true) {
return;
}
throw new BroadcastException( // <-- Exception at this line
is_bool($response) ? 'Failed to connect to Pusher.' : $response['body']
);
}
/**
* Get the Pusher SDK instance.
*
* #return \Pusher\Pusher
*/
public function getPusher()
{
return $this->pusher;
}
}
I've looked at a few other stack overflow articles which talk about changing encrypted: true to encrypted: false but that does not seem to affect anything.
I started working on Laravel 4 days ago and I came across this same problem when I was implementing a real-time chat application. After searching for many days, I discovered that this may vary depending on the version of Laravel you are running. If it is 5.8, you can fix this by adding the following code in the pusher.options array of the file config/broadcasting.php:
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
],
After adding this , your pusher array in the config/broadcasting.php should look like this.
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
],
],
],
You can then run php artisan config:cache(which may not be necessary in some cases) and finally run php artisan serve.You can consult your app in the pusher website and see the events you receive after sending your messages.
Hope it helps!!
If you're working on localhost try setting your .env file.
Set:
APP_URL=http://localhost
DB_HOST=localhost
And run
php artisan config:cache
Like i mentioned in a comment before this happens when the whole post goes wrong and wont deliver a response. Thats why the exception in line 116 is raised. I changed it to the domain before!
In my case i followed the code an found the method "createPusherDriver" in "vendor/laravel/framework/src/Illuminate/Broadcasting/BroadcastManager.php". At this place i inserted this
var_dump($config['key']);
var_dump($config['secret']);
var_dump( $config['app_id']);
var_dump($config['options']);
exit;
an noticed that my options still listed "host" => "localhost".
I removed those lines an cleared the config cache by executing php artisan config:cache
On next reload my event was fired an logged in the console.
Worked perfectly up to my Laravel 5.8 version. But encrypted' => true or encrypted' => false did not matter in this case for such Laravel version. But, following PUSHER suggestions, I put to broadcasting: 'useTLS' => true,.
This is the final result to me:
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
'useTLS' => true,
'curl_options' => [
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_SSL_VERIFYPEER => 0,
],
]
Thanks to dear #Bitart
'useTLS' => true
option solved my issue.
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true,
]

Laravel 5.4 pusher error

I am using pusher in Laravel 5.4 but I'm getting following error:
WebSocket connection to 'ws://ws.pusherapp.com/app/731e32c5f123456298e?protocol=7&client=js&version=4.1.0&flash=false' failed: WebSocket is closed before the connection is established.
Pusher : Error : {"type":"WebSocketError","error":{"type":"PusherError","data":{"code":4001,"message":"Did you forget to specify the cluster when creating the Pusher instance? App key 731e32c5f123456298e does not exist in this cluster."}}}
It looks like you've copied your pusher app_key incorrectly. Pusher app keys typically have 20 characters, yours has 19.
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_KEY'),
'secret' => env('PUSHER_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => <your cluster> ,
'encrypted' => true,
],
],
Specify your cluster
however if you are testing on localhost encrypted should be false
I was facing the same issue and fixed it by adding cluster in Pusher function call of javascript:
var pusher = new Pusher('PUSHER_APP_KEY', {
cluster: 'PUSHER_APP_CLUSTER'
encrypted: true
});

How to use functions in services.php laravel config file

I needed to use a dynamic callback url for socialite so I added the url() function to my services.php file it worked fine(and its still working on my live server) But when tried to start the project locally I get the following error. When I remove the url() method everything works fine please help.
PHP Fatal error: Uncaught ReflectionException: Class log does not exist in /home/fenn/projects/jokwit/vendor/laravel/framework/src/Illuminate/Container/Container.php:734
Stack trace:
#0 /home/fenn/projects/jokwit/vendor/laravel/framework/src/Illuminate/Container/Container.php(734): ReflectionClass->__construct('log')
#1 /home/fenn/projects/jokwit/vendor/laravel/framework/src/Illuminate/Container/Container.php(629): Illuminate\Container\Container->build('log', Array)
#2 /home/fenn/projects/jokwit/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(697): Illuminate\Container\Container->make('log', Array)
#3 /home/fenn/projects/jokwit/vendor/laravel/framework/src/Illuminate/Container/Container.php(849): Illuminate\Foundation\Application->make('log')
#4 /home/fenn/projects/jokwit/vendor/laravel/framework/src/Illuminate/Container/Container.php(804): Illuminate\Container\Container->resolveClass(Object(ReflectionParameter))
#5 /home/fenn/projects/jokwit/vendor/laravel/framework/src/Illuminate/Container/Container.php(7 in /home/fenn/projects/jokwit/vendor/laravel/framework/src/Illuminate/Container/Container.php on line 734
Here is my services.php file
<?php
return [
/*
|--------------------------------------------------------------------------
| Third Party Services
|--------------------------------------------------------------------------
|
| This file is for storing the credentials for third party services such
| as Stripe, Mailgun, Mandrill, and others. This file provides a sane
| default location for this type of information, allowing packages
| to have a conventional place to find your various credentials.
|
*/
'mailgun' => [
'domain' => env('MAILGUN_DOMAIN'),
'secret' => env('MAILGUN_SECRET'),
],
'mandrill' => [
'secret' => env('MANDRILL_SECRET'),
],
'ses' => [
'key' => env('SES_KEY'),
'secret' => env('SES_SECRET'),
'region' => 'us-east-1',
],
'stripe' => [
'model' => App\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_SECRET'),
],
'facebook' => [
'client_id' => '1700935300171729',
'client_secret' => 'XXXXXXXXXXXXXXXXXXX',
'redirect' => url('/facebook/callback'),
],
'google' => [
'client_id' => 'XXXXXXXXXXXXXXXXXXXXXXXX',
'client_secret' => 'XXXXXXXXXXXXXXXXXXXXXXXX',
'redirect' => url('google/callback'),
],
];
In services.php file
...
'redirect' => 'google/callback',
...
Next create service provider for example ConfigServiceProvider
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class ConfigServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
//
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
\Config::set("services.google.redirect", url(\Config::get('services')['google']['redirect']));
}
}
now should work fine
It doesn't work because in production Laravel cached all configuration files and using this cache. In development environment Laravel didn't create cache.
You can check it by commenting url() in config and then running php artisan config:cache command. Uncomment url() part and you'll see error is disappeared.
The best you can do here is to not use Laravel or manually defined functions in config files and find another solution for your problem.

Change S3 Endpoint in Laravel

I used the filesystems.php file to configure my S3.
When I try to put content in the bucket I receive this error:
Encountered a permanent redirect while requesting https://s3-us-west-2.amazonaws.com/MYBUCKET... Are you sure you are using the correct region for this bucket?
I then try to acces the url and I get this message:
The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.
On the same page I get:
<Endpoint>s3.amazonaws.com</Endpoint>
Then how could I remove the region from the URL Laravel generates?
You can create a customer service provider like that:
use Illuminate\Support\ServiceProvider;
use Aws\S3\S3Client;
use League\Flysystem\AwsS3v3\AwsS3Adapter;
use League\Flysystem\Filesystem;
use Aws\Laravel\AwsServiceProvider;
use Storage;
class AwsS3ServiceProvider extends ServiceProvider
{
/**
* Perform post-registration booting of services.
*
* #return void
*/
public function boot()
{
Storage::extend('s3', function($app, $config) {
$client = new S3Client([
'credentials' => [
'key' => $config['key'],
'secret' => $config['secret'],
],
'region' => $config['region'],
'version' => $config['version'],
'endpoint' => $config['endpoint'],
'ua_append' => [
'L5MOD/' . AwsServiceProvider::VERSION,
],
]);
return new Filesystem(new AwsS3Adapter($client, $config['bucket_name']));
});
}
/**
* Register bindings in the container.
*
* #return void
*/
public function register()
{
//
}
}
And add endpoint variable into config/filesystems.php as well:
's3' => [
'driver' => 's3',
'key' => env('AWS_KEY'),
'secret' => env('AWS_SECRET'),
'region' => env('AWS_REGION'),
'version' => 'latest',
'endpoint' => env('AWS_ENDPOINT'),
'bucket_name' => env('AWS_BUCKET_NAME')
]
Look at docs to get details about how to extend Storage facade.
The simplest approach is to create a new disk that uses the S3 driver in config/filesystems.php. You don't need to create a service provider - the S3 driver will pick up the endpoint from the disk config if supplied.
'spaces' => [
'driver' => 's3',
'key' => env('DO_SPACES_KEY'),
'secret' => env('DO_SPACES_SECRET'),
'endpoint' => 'https://nyc3.digitaloceanspaces.com',
'region' => 'nyc3',
'bucket' => env('DO_SPACES_BUCKET'),
],
Set the DO_SPACES_KEY, DO_SPACES_SECRET and DO_SPACES_BUCKET environment variables to the appropriate values.
Source: https://laracasts.com/discuss/channels/laravel/custom-file-driver-digital-ocean-spaces?page=1
You can use this package https://github.com/aws/aws-sdk-php-laravel
In this package you can specify your settings in config file as desired.
The specific bucket is not created in AWS, so please create a bucket in AWS, and use same bucket at filesystem config, the issue will be resolved.

Categories