Как разрешить подключение к laravel-echo-server (redis + socket.io) во vue компонентах только авторизованным пользователям?

Имеется приложение с перепиской между пользователями и возможностью публиковать статьи в реальном времени (на websocket). Приложение SPA, имеется Laravel Passport аутентификация через токен, соответственно к каждому запросу в заголовке должен быть прикреплен токен.
При авторизации в VUEX вызывается мутация, которая сохраняет токен в локальном хранилище и изменяет состояние вошел ли пользователь в систему. (state.isLoggedIn)
loginUser(state, data) {
            state.isLoggedIn = true;            
            localStorage.setItem('token', data.access_token);            
        },

Для обычных axios запросов через интерсепторы добавляется заголовок с токеном к каждому запросу:
axios.interceptors.request.use(function (config) {       
        config.headers.Authorization = 'Bearer ' + localStorage.getItem('token');
        return config;
    }, function (err) {       
        return Promise.reject(err);
    });

В файле app.js настройки laravel-echo-server:
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')
        },
    },
});

В BroadcastServiceProvider:
Broadcast::routes(['middleware' => ['auth:api']]);
Соответственно, если пользователь авторизуется впервые, у него еще нет в хранилище localStorage.getItem('token') и сервер его не пропустит (Придется обновлять страницу).
Экземпляр vue создается вот так:
const app = new Vue({
    el: '#app',
    router,
    store,
    components: {
        MainApp
    },
});

Есть идея создать watcher в MainApp vue-компоненте который следит за состоянием в vuex (state.isLoggedIn) и после этого там вызывать код с настройками laravel-echo-server, правда немного не понимаю как это реализовать. Может быть есть еще какой-либо способ?
Update: На данный момент удалось реализовать вот так, может быть есть способ без использования 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}) => {
                           ...
                            }
                        })
                }
            }
        }
  • Вопрос задан
  • 835 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы