E
E
Evgeny Khripunov2018-07-22 20:27:11
Laravel
Evgeny Khripunov, 2018-07-22 20:27:11

How to allow only authorized users to connect to laravel-echo-server (redis + socket.io) in vue components?

There is an application with correspondence between users and the ability to publish articles in real time (on websocket). SPA application , there is Laravel Passport authentication through a token , so a token must be attached to each request in the header .
Upon authorization in VUEX , a mutation is invoked that stores the token in local storage and changes the state of whether the user is logged in. ( state.isLoggedIn )

loginUser(state, data) {
            state.isLoggedIn = true;            
            localStorage.setItem('token', data.access_token);            
        },

For regular axios requests via interceptors, a header with a token is added to each request:
axios.interceptors.request.use(function (config) {       
        config.headers.Authorization = 'Bearer ' + localStorage.getItem('token');
        return config;
    }, function (err) {       
        return Promise.reject(err);
    });

In app.js file laravel-echo-server settings:
import Echo from "laravel-echo"
window.io = require('socket.io-client');
window.Echo = new Echo({
    broadcaster: 'socket.io',
    host: window.location.hostname + ':6001',
    auth: {
        headers: {
            Authorization: 'Bearer ' + localStorage.getItem('token')
        },
    },
});

In BroadcastServiceProvider : Accordingly, if the user logs in for the first time, he does not yet have localStorage.getItem('token') in the store and the server will not let him through (We will have to refresh the page). The vue instance is created like this:
Broadcast::routes(['middleware' => ['auth:api']]);

const app = new Vue({
    el: '#app',
    router,
    store,
    components: {
        MainApp
    },
});

There is an idea to create a watcher in the MainApp vue-component that monitors the state in vuex ( state.isLoggedIn ) and after that call the code with the laravel-echo-server settings there, though I don’t understand how to implement this. Maybe there is another way?
Update: At the moment it was possible to implement like this, maybe there is a way without using the watcher?
watch: {
            isLoggedIn: function (val) {
                if (val === true) {
                    window.Echo = new Echo({
                        broadcaster: 'socket.io',
                        host: window.location.hostname + ':6001',
                        auth: {
                            headers: {
                                Authorization: 'Bearer ' + localStorage.getItem('token')
                            },
                        },
                    });
                    window.Echo.private('room.' + this.user_id)
                        .listen('PrivateChat', ({data}) => {
                           ...
                            }
                        })
                }
            }
        }

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question