I run Laravel 9 app with :
vue 3.2.37
vite 2.9.15
pusher/pusher-php-server 7.0
laravel-echo 1.14.0
All it's work nice on localhost, but on server I have this two events in devtools->network->ws when it try to connect to the channel :
1st : {"event":"pusher:connection_established","data":"{\"socket_id\":\"137307.1921357\",\"activity_timeout\":120}"}
and the 2nd : {"event":"pusher:error","data":{"code":4009,"message":"Connection not authorized within timeout"}}
I have already enable Authorised Connections in my Pusher App settings but I don't know from where this unauthorized error come. It occured just on server side, on localhost I have a subscribed event and there is a different between sockets shown in dev tools on localhost and on server :
localhost : two sockets are shown : ws://localhost:3000/ and wss://ws-eu.pusher.com/app/App_key?protocol=7&client=js&version=7.4.0&flash=false
but on server there is just one : wss://ws-eu.pusher.com/app/App_key?protocol=7&client=js&version=7.4.0&flash=false
bootstrap.js
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
wsPort: 443, //import.meta.env.VITE_PUSHER_PORT ?? 80,
wssPort: 443, //import.meta.env.VITE_PUSHER_PORT ?? 443,
forceTLS: true, // (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
disableStats: true,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
enabledTransports: ['ws', 'wss'],
//authEndpoint: "https://support.demkit.fr/broadcasting/auth",
encrypted: true,
});
.env :
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=1******
PUSHER_APP_KEY=6******
PUSHER_APP_SECRET=8*********
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=eu
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
channels.php
Broadcast::channel('messages.{RoomId}', function ($user, $RoomId) {
//if(Auth::check())
//return ['id' => $RoomId];
return true; // I tried to return all time true to get authorization but it doesn't work :(
});
The error is occuring because your client is not subscribing to a private or presence channel within the timeout. When authorized connections are enabled then any connection that does not subscribe to such a channel will be terminated. https://pusher.com/docs/channels/using_channels/authorized-connections/
Either turn off this setting or subscribe to a private/presence channel to resolve.
Slution
I resolved this issue by adding customize the authorization endpoint check Customizing The Authorization Endpoint
docs from laravel
web.php :
Route::post('/pusher/user-auth', [PusherController::class, 'pusherAuth']);
PusherController :
/**
* Authenticates logged-in user in the Pusher JS app
* For private channels
*/
public function pusherAuth(Request $request)
{
$user = auth()->user();
$socket_id = $request['socket_id'];
$channel_name =$request['channel_name'];
$key = config('broadcasting.connections.pusher.key');
$secret = config('broadcasting.connections.pusher.secret');
$app_id = config('broadcasting.connections.pusher.app_id');
if ($user) {
$pusher = new Pusher($key, $secret, $app_id);
$auth = $pusher->socketAuth($channel_name, $socket_id);
return response($auth, 200);
} else {
header('', true, 403);
echo "Forbidden";
return;
}
}
and the bootstrap file :
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
wsPort: 443, //import.meta.env.VITE_PUSHER_PORT ?? 80,
wssPort: 443, //import.meta.env.VITE_PUSHER_PORT ?? 443,
forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
disableStats: true,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
enabledTransports: ['ws', 'wss'],
authEndpoint: "/pusher/user-auth", // this is the new endpoint for auth
encrypted: true,
});
and finaly don't froget to change the BROADCAST_DRIVER in .env file to pusher not log
Related
I have a laravel 9 App and vueJs 3. I use laravel pusher to send messages on real time and listen to channels in front-end with laravel echo like this :
Echo.private(`messages.${this.room.id}`).listen(".new-message", (e) => {
console.log("done")
this.chats.push({
message: e.message.message,
image_path : e.message.image_path,
from_id: e.from.id,
to_id: e.to.id,
from: e.from,
})
the configuration in bootstrap file:
import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
wsPort: import.meta.env.VITE_PUSHER_PORT ?? 80,
wssPort: import.meta.env.VITE_PUSHER_PORT ?? 443,
forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
enabledTransports: ['ws', 'wss'],
});
.env file :
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=1******
PUSHER_APP_KEY=6******
PUSHER_APP_SECRET=8*********
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=eu
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
all works fine at localhost and messages was recieving at real time, but when I deploy the app on server , it's not working , I can't listen to the channel. I don't know if I must append another configuration
Any suggestions ?
thank's
Slution
I resolved this issue by adding customize the authorization endpoint check Customizing The Authorization Endpoint
docs from laravel
web.php :
Route::post('/pusher/user-auth', [PusherController::class, 'pusherAuth']);
PusherController :
/**
* Authenticates logged-in user in the Pusher JS app
* For private channels
*/
public function pusherAuth(Request $request)
{
$user = auth()->user();
$socket_id = $request['socket_id'];
$channel_name =$request['channel_name'];
$key = config('broadcasting.connections.pusher.key');
$secret = config('broadcasting.connections.pusher.secret');
$app_id = config('broadcasting.connections.pusher.app_id');
if ($user) {
$pusher = new Pusher($key, $secret, $app_id);
$auth = $pusher->socketAuth($channel_name, $socket_id);
return response($auth, 200);
} else {
header('', true, 403);
echo "Forbidden";
return;
}
}
and the bootstrap file :
window.Echo = new Echo({
broadcaster: 'pusher',
key: import.meta.env.VITE_PUSHER_APP_KEY,
wsHost: import.meta.env.VITE_PUSHER_HOST ?? `ws-${import.meta.env.VITE_PUSHER_APP_CLUSTER}.pusher.com`,
wsPort: 443, //import.meta.env.VITE_PUSHER_PORT ?? 80,
wssPort: 443, //import.meta.env.VITE_PUSHER_PORT ?? 443,
forceTLS: (import.meta.env.VITE_PUSHER_SCHEME ?? 'https') === 'https',
disableStats: true,
cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
enabledTransports: ['ws', 'wss'],
authEndpoint: "/pusher/user-auth", // this is the new endpoint for auth
encrypted: true,
});
and finaly don't froget to change the BROADCAST_DRIVER in .env file to pusher not log
I'm trying to get a mqtt connection on my browser with JS
I'm following this tutorial: https://emqx.medium.com/use-websocket-to-connect-to-mqtt-broker-9e7baf1aa773
So I've got this:
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js" type="text/javascript"></script>
<script>
// Globally initializes an mqtt variable
const clientId = 'mqttjs_' + Math.random().toString(16).substr(2, 8)
const host = 'ws://broker.***.***.com:9883'
const options = {
keepalive: 60,
clientId: clientId,
username: '***',
password: '***',
protocolId: 'MQTT',
protocolVersion: 4,
clean: true,
reconnectPeriod: 1000,
connectTimeout: 30 * 1000,
will: {
topic: 'WillMsg',
payload: 'Connection Closed abnormally..!',
qos: 0,
retain: false
},
}
console.log('Connecting mqtt client')
const client = mqtt.connect(host, options)
client.on('connect', () => {
console.log('Client connected:' + clientId)
// Subscribe
})
</script>
And in my browser I've got this error:
After some research, some people say that need to use certificate: https://github.com/eclipse/paho.mqtt.javascript/issues/187
So, I've got this :
<script src="../browserMqtt.js"></script>
<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script>
var options = {
keyPath: '../credentials/client-key.pem',
certPath: '../credentials/client-cert.pem',
rejectUnauthorized : false,
ca: ['../credentials/a-cert.pem'],
protocolId: 'MQTT',
username: '***',
password: '***',
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8)
};
var client = mqtt.connect('ws://broker.***.***.com:9883',options);
client.on('connect', function(){
console.log('Connected');
});
</script>
I've got the same error in browser ...
The broker conguration for mosquitto, it's like this :
allow_anonymous false
password_file /mosquitto/config/passwd
#TCP
listener 1883
socket_domain ipv4
#SSL
listener 8883
socket_domain ipv4
cafile /mosquitto/config/tls/ca/ca-cert.pem
certfile /mosquitto/config/tls/server/server-cert.pem
keyfile /mosquitto/config/tls/server/server-key.pem
tls_version tlsv1.2
socket_domain ipv4
#WSS
listener 9883
socket_domain ipv4
protocol websockets
cafile /mosquitto/config/tls/ca/ca-cert.pem
certfile /mosquitto/config/tls/server/server-cert.pem
keyfile /mosquitto/config/tls/server/server-key.pem
tls_version tlsv1.2
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
log_timestamp_format %Y-%m-%dT%H:%M:%S
log_type all
I can't understand how can I solve it ? Thanks for your help
You can't use client side certs in the browser to authenticate the client (unless you load them into the browsers keystore, but even then I'm not convinced it will work unless there is only one cert/key for the browser to pick as javascript code won't normally prompt the user to pick the right one).
Also loading client certs over http from the server totally defeats the point of using a client cert as anybody can download them.
You need to remove all of the following from the options
keyPath: '../credentials/client-key.pem',
certPath: '../credentials/client-cert.pem',
rejectUnauthorized : false,
ca: ['../credentials/a-cert.pem'],
protocolId: 'MQTT',
Because the paths are meaningless in the browser (and for the reasons I mentioned earlier)
You should also be starting your broker URL with wss:// to make it clear you are trying to connect over secure WebSockets.
I am using pusher-js in react. My frontend is served at app.xxx.com and my backend is served at api.xxx.com. We have a private notification websocket channel to push notiifcations through app.xxx.com. What i'm trying to achieve is using the auth endpoint on backend. But no matter what i do, pusher will always request to the base URL of frontend plus auth endpoint. In my case it will be https://app.xxx.com/broadcasting/auth but i want it to be https://api.xxx.com/broadcasting/auth. What should i do? Here's my pusher config:
pusher = new Pusher(APP_ID, {
httpHost: process.env.REACT_APP_WS_HOST,
authEndpoint: '/broadcasting/auth',
auth: {
params: {
id: userData.id,
},
headers: {
'X-CSRF-Token': '{{ csrf_token() }}'
}
},
cluster: 'ap2',
wsHost: process.env.REACT_APP_WS_HOST,
wsPort: 6001,
wssPort: 6001,
forceTLS: true,
})
The value of process.env.REACT_APP_WS_HOST is api.xxx.com
UPDATE:
I even tried adding an authHost key but nothing changed.
You should be able to use the full URL to the endpoint:
authEndpoint: 'https://api.xxx.com/broadcasting/auth'
I have a Pubnub instance,
I want to know how to handle reconnection when internet does down and comes back up with like a given number of retries? The documentation definitely gives the appropriate docs but I am unable to put it into code.
Help would be greatly appreciated.
my code:
this.pubnub = new PubNub({
subscribeKey: this.serverDetails.authInfo.subscribeKey,
authKey: this.serverDetails.authInfo.authKey,
uuid,
restore: true,
ssl: true
});
this.listeners = {
message: msgEvent => {
console.log(msgEvent);
},
status: statusEvent => {
}
};
this.pubnub.addListener(this.listeners);
Set restore:true in your init code.
this.pubnub = new PubNub({
subscribeKey: this.serverDetails.authInfo.subscribeKey,
authKey: this.serverDetails.authInfo.authKey,
uuid,
ssl: true,
restore: true // this allows reconnect to restore your channel subscription
});
I want to set the primary dns , secondary dns of node js server.
But i use 'setup' module , there are only dns , not secondary dns.
Like this
var setup = require('setup')();
var config = setup.network.config({
wlan0: {
auto: true, // start at Boot
dhcp: true, // Use DHCP
wireless: {
ssid: 'myWirelessName', // Wireless SSID
psk: 'mySuperPassword', // Password
}
},
eth0: {
auto: true,
ipv4: {
address: '192.168.1.20',
netmask: '255.255.255.0',
gateway: '192.168.1.1',
dns: '8.8.8.8'
}
}
});
how can i set primary dns and secondary dns of the node js?
I would appreciate your help.