How to guard private channels when using socket.io and Laravel Echo?
Asked Answered
R

1

7

Here is my server.js file:

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var Redis = require('ioredis');
var redis = new Redis();

http.listen(3000, function(){
    console.log('Listening on Port 3000');
});

redis.psubscribe('*', function(err, count) {
    console.log(err, count);
});
redis.on('pmessage', function(subscribed, channel, message) {
    message = JSON.parse(message);
    io.emit(message.event, channel, message.data);
});

And a simple event:

class FieldWasUpdated implements ShouldBroadcast
{
    use InteractsWithSockets, SerializesModels;
    public $instance;
    public $key;
    public $value;

    public function __construct($instance, $key, $value)
    {
        $this->instance = $instance;
        $this->key = $key;
        $this->value = $value;
    }

    public function broadcastOn()
    {
        return new PrivateChannel("model." . $this->instance->getModelType() . "." . $this->instance->id);
    }
}

The client connects to socket.io:

Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':3000'
});

And then listens for events (it is inside a Blade template):

var channel = "model.{{ $instance->getModelType() }}.{{ $instance->id }}";
Echo.private(channel)
    .listen("FieldWasUpdated", function(e) {
        window.VueBus.$emit("updated", channel, e.key, e.value);
    })
    .listen("FieldBecameDisabled", function(e) {
        window.VueBus.$emit("disabled", channel, e.key);
    });

Problem is: authentication is not handled, any user can subscribe to these channels.

Broadcast::channel("model.announcement.*", function($user, $id) {
    return false; // this function is not called
})

Here is a sample event from the Chrome developer console (WebSocket):

[
    "App\\Events\\FieldWasUpdated",
    "private-model.announcement.2",
    {
        "instance":
        {
            "type":"ANN_TYPE_MISSED_CALL",
            "status":"ANN_STATUS_CANCELLED",
            "name":"1233421",
            "phone":"+7(222)222-3322",
            "email":"[email protected]",
            "message":"sdgdsgsdgdfdg",
            "requirement":null,
            "web_type":"ANN_WEB_TYPE_UNKNOWN",
            "url":null,
            "responsible_id":19,
            "recommender_id":18
        },
        "key":"message",
        "value":"sdgdsgsdgdfdg"
    }
]

Also there is no /broadcast/auth URL, but BroadcastServiceProvider has a call to Broadcast::routes(); and when the browser loads, no calls to /broadcast/auth occur.

Redintegrate answered 7/2, 2017 at 9:51 Comment(1)
try Broadcast::channel("model.announcement.*", function($user, $id) { abort(401); })Tailback
E
0

The Laravel documentation goes into detail about this in the Broadcasting chapter: https://laravel.com/docs/5.5/broadcasting#presence-channels. The Authorizing Presence Channels section should be the same for private channels.

Embryogeny answered 31/12, 2017 at 17:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.