Skip to content
This repository was archived by the owner on Feb 7, 2024. It is now read-only.

difficulties getting multi-tenancy to work #23

Closed
vesper8 opened this issue Dec 6, 2018 · 5 comments
Closed

difficulties getting multi-tenancy to work #23

vesper8 opened this issue Dec 6, 2018 · 5 comments

Comments

@vesper8
Copy link

vesper8 commented Dec 6, 2018

Ok so I'm trying to decouple the demo repository into two installations. And I'll also be using the "server-only" installation to work with all my other projects that currently use Pusher.

So I created a new mysql database 'db_socketmaster' and set it inside .env

laravel new socketmaster
cd socketmaster
composer require beyondcode/laravel-websockets
composer require pusher/pusher-php-server "~3.0" (as per instructions but seems redundant since this is a dependency of beyondcode/laravel-websockets)
pa key:generate
pa migrate
pa vendor:publish (to publish the config and migrations from websockets)

I'm running this off Valet with --secure

In my websockets.php. I added the necessary entries to the SSL part as per the new Valet configuration.. no problem there

Then in the apps section I added this

    'apps' => [
        [
            'id' => '4036967643',
            'name' => 'site-1',
            'key' => 'E2fAKqHM0EvOAL',
            'secret' => 'InMBQzUtRueKdf',
            'enable_client_messages' => false,
            'enable_statistics' => true,
        ],
        [
            'id' => '6641070849',
            'name' => 'site-2',
            'key' => '7kWyUamVkIaAZw',
            'secret' => 'iLKvyU3f3ftzJK',
            'enable_client_messages' => false,
            'enable_statistics' => true,
        ],
        [
            'id' => '9566892751',
            'name' => 'site-3',
            'key' => 'zRr6ThwvOPoIeK',
            'secret' => 'HufIJdYCfWDGBh',
            'enable_client_messages' => false,
            'enable_statistics' => true,
        ],
        [
            'id' => '2856995658',
            'name' => 'websockets-demo',
            'key' => 'gzfYlnfja2LiS4',
            'secret' => '1jHb1sxlhavkS8',
            'enable_client_messages' => false,
            'enable_statistics' => true,
        ],
        // [
        //     'id' => '',
        //     'name' => '',
        //     'key' => '',
        //     'secret' => '',
        //     'enable_client_messages' => false,
        //     'enable_statistics' => true,
        // ],
    ],

Ignore the first 3, so the 4th one is for the laravel-websockets-demo. I used a random generator to generate all the fake app IDs and key/secrets

I set the broadcast driver to pusher (or in my case pusher-dev)

And then inside broadcasting.php config file, this is where I'm confused

I put this

        'pusher' => [
            'driver' => 'pusher',
            // 'key' => env('PUSHER_APP_KEY'),
            // 'secret' => env('PUSHER_APP_SECRET'),
            // 'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                // 'cluster' => env('PUSHER_APP_CLUSTER'),
                'encrypted' => true,
                'host' => '127.0.0.1',
                'port' => 6001,
                'scheme' => 'https',
            ],
        ],

        'pusher-dev' => [
            'driver' => 'pusher',
            // 'key' => env('PUSHER_APP_KEY'),
            // 'secret' => env('PUSHER_APP_SECRET'),
            // 'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                // 'cluster' => env('PUSHER_APP_CLUSTER'),
                'encrypted' => true,
                'host' => '127.0.0.1',
                'port' => 6001,
                'scheme' => 'https',
                'curl_options' => [
                    CURLOPT_SSL_VERIFYHOST => 0,
                    CURLOPT_SSL_VERIFYPEER => 0,
                ],
            ],
        ],  

I set another connection "pusher-dev" because on production I don't want to disable the host verification. I set the scheme to https for both.. and where I'm confused is.. what am I supposed to put for the key/secret/app_id ? since this is not for any particular app but is managing multiple apps

So I just commented out those values. Also I think the cluster is redundant at this point am I right?

I ran php artisan websockets:serve, no errors here

Then I modified the bootstrap.js inside the demo to this:

window.Echo = new Echo({
    broadcaster: 'pusher',
    // key: process.env.MIX_PUSHER_APP_KEY,
    // wsHost: window.location.hostname,
    key: 'gzfYlnfja2LiS4',
    wsHost: 'socketmaster.dev',
    wsPort: 6001,
    wssPort: 6001,
    disableStats: true,
});

I'm using the "key" from the 4th app, the 'websocket-demo' app. And for the host I'm using my "socket manager" url, which is correct. I'm able to visit the debug dashboard at https://socketmaster.dev/laravel-websockets

I ran npm run prod

And then I visited the chat demo, logged in. I get no errors in the console or the network tab. But in my terminal running the websockets I get an 'Invalid Signature' error

New connection opened for app key gzfYlnfja2LiS4.
Connection id 125098324.201156164 sending message {"event":"pusher:connection_established","data":"{\"socket_id\":\"125098324.201156164\",\"activity_timeout\":30}"}
2856995658: connection id 125098324.201156164 received message: {"event":"pusher:subscribe","data":{"auth":"websocketkey:34efbef0371bee17728389eb9b08f4dd53077ee2cccaadfe90f7a0637db67a34","channel_data":"{\"user_id\":1,\"user_info\":{\"id\":1,\"name\":\"Charlie\",\"email\":\"[email protected]\",\"email_verified_at\":null,\"created_at\":\"2018-12-05 02:10:01\",\"updated_at\":\"2018-12-05 02:10:01\"}}","channel":"presence-chat"}}.
Exception `BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature` thrown: `Invalid Signature`
2856995658: exception `BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature` thrown: `Invalid Signature`.
Connection id 125098324.201156164 sending message {"event":"pusher:error","data":{"message":"Invalid Signature","code":4009}}
2856995658: connection id 943809179.970880291 received message: {"event":"pusher:ping","data":{}}.
Connection id 943809179.970880291 sending message {"event":"pusher:pong"}

I also gets CORS errors afterwards

Is this purely a CORS issue?

My 'allowed_origins' array is left empty on socketmaster's websockets.php configuration

@mpociot
Copy link
Member

mpociot commented Dec 6, 2018

Okay here's what might confuse you:

When one of your apps (for example the demo) tries to connect to a private or presence channel on your WebSocket server, it sends an authentication signature. This signature gets generated by Laravel using the credentials in the broadcasting.php file.

You can completely ignore the broadcasting.php file on your socketmaster.

But your apps / the websockets-demo application should still have this in the config:

'pusher' => [
    'driver' => 'pusher',
    'key' => env('PUSHER_APP_KEY'),
    'secret' => env('PUSHER_APP_SECRET'),
    'app_id' => env('PUSHER_APP_ID'),
    'options' => [
        'cluster' => env('PUSHER_APP_CLUSTER'),
        'encrypted' => true,
        'host' => 'socketmaster.dev',
        'port' => 6001,
        'scheme' => 'https',
        'curl_options' => [
            CURLOPT_SSL_VERIFYHOST => 0,
            CURLOPT_SSL_VERIFYPEER => 0,
        ]
    ],
],

@vesper8
Copy link
Author

vesper8 commented Dec 6, 2018

Going to try it out and re-open the issue if I run into more problems. Thanks for the answer!

@vesper8 vesper8 closed this as completed Dec 6, 2018
@vesper8
Copy link
Author

vesper8 commented Dec 7, 2018

HI @mpociot, following up.. I reset my socketmaster's broadcasting.php to its default settings (scheme http, no curl options) as you said I can completely ignore that one.

My socketmaster's websockets.php config has the crt and key file pointed to and verify_peer set to false, and the apps added as mentioned in my first post

On the demo's side. I added the correct values from the demo app inside the .env and the only modifications in the bootstrap.js are these two lines

wsHost: 'socketmaster.dev',
wssPort: 6001

Rebuilt the demo app.js and connected two users. Yay the chat works now, the socketmaster is handling it correctly it seems.. super

Only problem left is when I try connecting to the socketmaster's debug dashboard and I connect to the demo app on port 6001. It allows me to connect and it populates the graph. But it doesn't show any events and in the terminal it prints this error

New connection opened for app key gzfYlnfja2LiS4.
Connection id 544391830.59395373 sending message {"event":"pusher:connection_established","data":"{\"socket_id\":\"544391830.59395373\",\"activity_timeout\":30}"}
2856995658: connection id 544391830.59395373 received message: {"event":"pusher:subscribe","data":{"auth":":8e9b0c079a355b43e6b88f8c298a006def048d292984c7f973c6ca1aca80e02c","channel":"private-websockets-dashboard-disconnection"}}.
Exception `BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature` thrown: `Invalid Signature`
2856995658: exception `BeyondCode\LaravelWebSockets\WebSockets\Exceptions\InvalidSignature` thrown: `Invalid Signature`.
Connection id 544391830.59395373 sending message {"event":"pusher:error","data":{"message":"Invalid Signature","code":4009}}
Connection id 544391830.59395373 closed.

@vesper8 vesper8 reopened this Dec 7, 2018
@vesper8
Copy link
Author

vesper8 commented Dec 7, 2018

Hi @mpociot, continuing on with my attempt to set up multi-tenancy to have my socketmaster handle connections for the demo as well as existing apps that were using pusher.. I've run into more trouble.

For this other application. I have a front-end built with vue-cli and a completely decoupled rest api built with Laravel. It was previously set up to work with Pusher to make use of presence channels (see who is online) and private channels (for notifications)

on the vue-cli side, I've modified my echo connection from

  window.Echo = new Echo({
    broadcaster: 'pusher',
    key: '0c4c86f701720f83650c9', // pusher key
    cluster: 'mt1',
    encrypted: true,
  });

to

  window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'zRr6ThwvOPoIeK', // laravel-websockets key
    wsHost: 'socketmaster.dev',
    wsPort: 6001,
    wssPort: 6001,
    disableStats: true,
  });

it's not clear to me by the way what does the 'disableStats' do here. I thought stats are strictly enabled/disabled in the app configuration in websockets.php

ok, rebuilt the app.. and then on the Laravel REST API end, I modified the .env values and modified the broadcasting.php config to

        'pusher-dev' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'encrypted' => true,
                'host' => 'socketmaster.dev',
                'port' => 6001,
                'scheme' => 'https',
                'curl_options' => [
                    CURLOPT_SSL_VERIFYHOST => 0,
                    CURLOPT_SSL_VERIFYPEER => 0,
                ],
            ],
        ],    

At first I left the host to 127.0.0.1 but since my privateChannel notifications weren't working I figured this needed to be changed to socketmaster.dev

So with this configuration, my presence channels DO work.. however my private channel notifications don't work. Those are initiated from the server (I have a test endpoint that I visit and it is supposed to notify the specified user).

The api endpoint looks like /admin/broadcast/user/{user}/message/{message}

So I hit it with /admin/broadcast/user/1/message/test

And it sends the message 'test' to user#1 provided he's connected.

In the terminal, when I reload my front-end, it does show that my user is connected to both the presence channel and the private channel:

New connection opened for app key zRr6ThwvOPoIeK.
Connection id 421526693.217375221 sending message {"event":"pusher:connection_established","data":"{\"socket_id\":\"421526693.217375221\",\"activity_timeout\":30}"}
9566892751: connection id 421526693.217375221 received message: {"event":"pusher:subscribe","data":{"auth":"zRr6ThwvOPoIeK:e68938e36577db4ee9ef60fe33835ac722c5f23997e0672732de233fd2f80689","channel":"private-notifications.1"}}.
Connection id 421526693.217375221 sending message {"event":"pusher_internal:subscription_succeeded","channel":"private-notifications.1"}
9566892751: connection id 421526693.217375221 received message: {"event":"pusher:subscribe","data":{"auth":"zRr6ThwvOPoIeK:90c6e2f0a3bb6410b70c0748ca0c080cff27e86c7dcc1cb27ebff7295e27df1e","channel":"private-App.User.1"}}.
Connection id 421526693.217375221 sending message {"event":"pusher_internal:subscription_succeeded","channel":"private-App.User.1"}
9566892751: connection id 421526693.217375221 received message: {"event":"pusher:subscribe","data":{"auth":"zRr6ThwvOPoIeK:67440e70aba9e4eba82a9d871589638e8648d1c35fd30f0ce465065986b64431","channel_data":"{\"user_id\":1,\"user_info\":{\"id\":1,\"username\":\"vesper8\"}}","channel":"presence-online"}}.
Connection id 421526693.217375221 sending message {"event":"pusher_internal:subscription_succeeded","channel":"presence-online","data":"{\"presence\":{\"ids\":[\"1\"],\"hash\":{\"1\":{\"id\":1,\"username\":\"vesper8\"}},\"count\":1}}"}

It does queue it up without error but the websockets:serve terminal never gets hit and nothing happens

So the problem is my rest api is unable to broadcast back to the user via the socketmaster.dev

As for the debug dashboard.. I have the same problem as above, I'm able to connect but get that Invalid Signature error and don't see any events.

Any idea what I'm doing wrong please?

@junaidrasheed
Copy link

junaidrasheed commented Jul 8, 2020

@mpociot , @vesper8 did you manage to solve this issue? I have a same scenario where I have multiple decoupled apps that would connect to my socket server. As suggested above my broadcasting.php is same as default.

My websockets.php in socket server

'apps' => [
       [
           'id' => env('PUSHER_APP_ID'),
           'name' => env('APP_NAME'),
           'key' => env('PUSHER_APP_KEY'),
           'secret' => env('PUSHER_APP_SECRET'),
           'enable_client_messages' => false,
           'enable_statistics' => true,
       ],
       [
           'id' => 'app1',
           'name' => 'app1',
           'key' => 'mykeyforapp1',
           'secret' => 'mysecretkeyforapp1',
           'enable_client_messages' => false,
           'enable_statistics' => true,
       ],
   ],

My bootstrap.js from a separate vuejs app

import Echo from 'laravel-echo';

window.Pusher = require('pusher-js');
window.Echo = new Echo({
    broadcaster: 'pusher',
    key: 'mykeyforapp1',
    wsHost: 'websocketapp.loc',
    wsPort: 6001,
    forceTLS: false,
    authEndpoint: 'http://websocketapp.loc/broadcasting/auth',
    disableStats: true,
    auth: {
        headers: {
            'Auth-Token': 'custom-token',
        }
    }
});

This connects and verifies user as expected by reading 'Auth-Token' from header, but also logs Invalid Signature 4009 error in the terminal. And I'm not receiving any broadcasted event either on public or private channel. But if I use PUSHER_APP_KEY defined for default socket server app it works as expected and I receive all the events.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants