Comments (15)
Yeah I've got some ideas on how to secure channels. I'm working on adding something like this to an API for an app I'm building. I'll throw out some examples namespaced with "echo" in hopes that it will convince. 😄
Server-side - Node (New npm package?)
var EchoServer = require('laravel-echo-server'); //I've got a working prototype
var echo = new EchoServer();
echo.run();
with options
var options = {
host: 'http://localhost:6001',
authEndpoint: '/broadcasting/auth', //endpoint to post authorization
privateChannels: ['notifications-*'] //assign private channels, default private-*
};
new EchoServer(options);
Server-side - PHP (New Laravel package?)
- When notifications are requested
GET /notifications
create a token associated to a userechoToken()->create($user, 'notifications-user-1')
- Return notifications along with a single-use echo_token
{notifications: [], echo_token: '...'}
- Node server POSTs the echo_token to Laravel to be authenticated
POST /broadcasting/auth
, if user's token matches the private-channel return200 OK
Client-side
var notifications;
var Echo = require('laravel-echo');
//initial request to notifications
fetch('/notifications').then(function(res) {
notifications = res.notifications;
var echo = new Echo({
provider: 'socket.io',
channel: 'notifications-user-1',
echo_token: res.echo_token
});
echo.listen('notifications-user-1', function () {
//listen for new notifications, only if authenticated
});
});
from echo.
Would be nice 😀
from echo.
Lack of good authentication mechanisms at the channel level is the main problem. If that can be solved cleanly that would be good.
from echo.
Just watched the Laracast on Echo! The new broadcast driver would eliminate the need of an additional package that issues tokens as I suggested above. Much cleaner approach @taylorotwell 👏 .
I looked at the 5.3-dev branch and noticed that the RedisBroadcaster would need to be updated like the PusherBroadcaster. Assuming that both pusher and socket.io would use the /broadcasting/auth
endpoint. I can send a PR, but is there anything else that I need to be aware of to make use of the new BroadcastServiceProvider?
Also, I'm having trouble pinpointing where the Broadcast::channel()
method is at. Is that feature finished yet?
I'm also still experimenting with some ideas on how to handle channel auth. I'm up to the point where I need to check auth with laravel before allowing a user to join a channel. Check this out:
https://github.com/tlaverdure/laravel-echo-server
Thanks!
from echo.
Cool :)
from echo.
ahem: https://github.com/leemason/rebound-client will have some docs and the redis/node server p tonight as well, stay tuned.
@taylorotwell i spoke to you about tis on twitter when you launched echo.
Ive spent along time trying to get socket.io to work and basically while possible, its alot of workarounds due to socket.io being so opinionated.
so i took engine.io and built a channel driven client (and server, nearly ready). im trying to keep the same api, but there are most likley going to be subtle differences.
from echo.
and heres the server package: https://github.com/leemason/rebound-server
@tlaverdure ive done it a different way, when a channel subscription is requested i send a post request to laravel with the original socket request headers (has all session stuff in it, and the socket id in a cookie).
the post requests either returns success=true and user object, or fails.
if it returns success the user object is saved against the socket on the node server, and added to a channels array.
when redis messages are fetched by the server, it doesnt just send to all sockets, it sends only to the sockets subscribed to that channel, and they cant be subcribed to that channel unless the post request was a success.
this way we offload all the auth stuff to laravel, and the node server simply passes messages along, theres no way for an unauthenticated socket to recieve messages as there not added to the channels.
its not socket io, but it has the same long polling fallbacks and reconnection stuff.
@taylorotwell is the interface for socket authentication routes, usable methods etc set in stone now for 5.3? id like to get a pull request ready and maintain a unified api if we can?
from echo.
Yes I think those methods are pretty solid so go ahead.
On Sun, May 22, 2016 at 12:45 PM -0700, "Lee Mason" [email protected] wrote:
and heres the server package: https://github.com/leemason/rebound-server
@tlaverdure ive done it a different way, when a channel subscription is requested i send a post request to laravel with the original socket request headers (has all session stuff in it, and the socket id in a cookie).
the post requests either returns success=true and user object, or fails.
if it returns success the user object is saved against the socket on the node server, and added to a channels array.
when redis messages are fetched by the server, it doesnt just send to all sockets, it sends only to the sockets subscribed to that channel, and they cant be subcribed to that channel unless the post request was a success.
this way we offload all the auth stuff to laravel, and the node server simply passes messages along, theres no way for an unauthenticated socket to recieve messages as there not added to the channels.
its not socket io, but it has the same long polling fallbacks and reconnection stuff.
@taylorotwell is the interface for socket authentication routes, usable methods etc set in stone now for 5.3? id like to get a pull request ready and maintain a unified api if we can?
—
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
from echo.
You could also store the channels in the session so you can join them on reconnect, would be annoying to make lots of extra requests on refresh.
Here is my implementation, but rooms are based on url (cause auth doesn't really in my app, and cannot join rooms any other way)
https://gist.github.com/lukepolo/58de479335e86ec2abba20f6c112f2fa
from echo.
yeah possibly, love that gist, does it work well for you?
personally id prefer to keep any sort of logic within the laravel app and run the socket server just as a intermediary which is what rebound is trying to solve, but as youve shown theres more than 1 way to skin a cat.
i dont like the idea of handling session and/or cookie information in two places, trying to let laravel handle all of that.
wasnt aware of that dotdev package, thats real nice, will add that to my examples.
from echo.
It works very well as I have been using this method for around 2 years on my application.
The reasoning behind touching the session is you can reject them ever connecting the server if they do not have a valid session. This is handy for rejecting anyone outside the application trying to connect.
I assume sure you know the socket.id change on every connect and you disconnect on all channels every refresh. To lower overhead on the number of requests you would store them in the session and use it in node. But I see your concern handling them in both places, but is that really a bad thing in this case ?
Ill look deeper into your code today ~
from echo.
yeah totally get your point, like i said your code is awesome. would be a good idea to add some sort of persistance.
the only reason i mention it, is it feels a bit hacky to deconstruct the encrypted laravel session in the node app, im still looking into it and your gist should help alot with that.
the aim of rebound really is to mimic the echo package, but be free usage AND be pretty much set and forget. had a good session on it today and yesterday and its in a working state, would love to see what you think.
from echo.
Awesome, ill try pulling in the latest changes and give it a go later tonight.
from echo.
yeah just reviewing your gist again to see if there are any quick wins. but not everybody is going to be using a redis session store (most likley as rebound uses redis for the events, but cant guarantee it).
still early days, we can optimize as we go along, 5.3 isnt even out yet so i think we have time.
from echo.
@lukepolo ive got round this now with the latest version. i open up another reis connection on the same db.
then when a socket gets saved in laravel, it returns the user id (if logged in). this gets saved against the socket.
when subscription to a channel happens, the cache is checked for "rebound:channel_name:user_id", which can contain the member info. (we saved the socket user id earlier on connect).
if cache missed = perform post auth check (and cache results)
if cache string is false = return without subscribing (auth failed)
if cache json parse and set member info from cache
this means the first visit forces the post request. every single request after that fetches the data from redis cache so no more post requests, and no session trickery.
take a look when you get chance.
from echo.
Related Issues (20)
- #listenToAll for NullConnector HOT 1
- #encryptedPrivate does not work with NullConnector HOT 1
- PresenceChannel interface missing 'Whisper' method HOT 2
- Implement `.listenOnce` and `.isListening` HOT 1
- [Bug] PresenceChannel interface missing 'Whisper' method HOT 2
- Nuxtjs + VUE 2 to update vue 3 + vite not working echo HOT 2
- Always got pusher ouput while using socket.io HOT 1
- Not subscribing to Echo when you open SPA as PWA from Homescreen HOT 4
- All the names of the events must be prefixed with a dot HOT 1
- Uncaught TypeError: event is undefined HOT 2
- Connection fails in Chrome, works just fine in FF HOT 1
- Export connectors and channels alongside with Echo and abstract classes HOT 2
- Laravel Echo with Socket.io HOT 1
- Centrifugo Connector HOT 1
- Fatal error when using channel.listen HOT 3
- Leave channel and disconnect right after HOT 1
- listen method does not work HOT 1
- Dont can get the returns of websocket
- dont cant get returns in console.log of the websocket, HOT 2
- ReferenceError: Property 'Pusher' doesn't exist HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from echo.