Jaeger
Jaeger

Reputation: 1716

Soketi & Echo doesn't work with SSL and doesn't authorize Private channels

Setup:

Issues:

Idea for first issue:

Suggestions:

Info:

.env

PUSHER_HOST=IP
PUSHER_APP_ID=APPID
PUSHER_APP_KEY=KEY
PUSHER_APP_SECRET=SECRET
PUSHER_APP_PORT=6002

PUSHER_APP_ENCRYPTED=true
PUSHER_APP_SCHEMA=https
PUSHER_APP_CLUSTER="eu-central-1"

MIX_PUSHER_HOST="${PUSHER_HOST}"
MIX_PUSHER_APP_PORT="${PUSHER_APP_PORT}"
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_ENCRYPTED="${PUSHER_APP_ENCRYPTED}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
MIX_PUSHER_PORT="${PUSHER_APP_PORT}"

auth.php

'defaults' => array(
        'guard' => 'web',
        'passwords' => 'users',
    ),

'guards' => array(
        'web' => array(
            'driver' => 'session',
            'provider' => 'users',
        ),

        'api' => array(
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ),
    ),

BroadcastServiceProvider

public function boot() {
        Broadcast::routes(['middleware' => ['auth:api']]);
        require base_path('routes/channels.php');
    }

Echo

window.Echo = new Echo({
    broadcaster: 'pusher',
    host: `${process.env.MIX_APP_HOST}:${process.env.MIX_PUSHER_APP_PORT}`,
    key: process.env.MIX_PUSHER_APP_KEY,
    wsHost: process.env.MIX_PUSHER_HOST,
    wsPort: process.env.MIX_PUSHER_PORT,
    wssPort: "6002",
    forceTLS: true,
    enabledTransports: ['ws', 'wss'],
    encrypted: process.env.MIX_PUSHER_APP_ENCRYPTED,
    reconnection: true,
    enableLogging: true,
    disableStats: true,
    authorizer: (channel, options) => {
        return {
            authorize: (socketId, callback) => {
                console.log("Requested something")
                axios.post('/api/broadcasting/auth', {
                    socket_id: socketId,
                    channel_name: channel.name
                })
                    .then(response => {
                        console.log(response)
                        callback(false, response);
                    })
                    .catch(error => {
                        callback(true, error);
                    });
            }
        };
    },
});

api.php

Route::prefix('broadcasting')->controller(BroadcastingController::class)->group(function () {
    Route::post('/auth', 'validateWebsocket');
});

BroadcastingController

public function validateWebsocket(Request $request) {
        Log::debug("socket_id: " . $request->get("socket_id") . ", channel_name: " . $request->get("channel_name"));
        return response()->json([], 200);
    }

Channels

Broadcast::channel('users.{userId}', function ($user, $userId) {
    Log::debug("Requesting");
    return empty($user) === false && $user->id == $userId;
});

Nginx

server { listen 6002 ssl http2; listen [::]:6002 ssl http2; server_name WEBSITE; server_tokens off;

  # FORGE SSL (DO NOT REMOVE!)
ssl_certificate /etc/nginx/ssl/WEBSITE/PATH/server.crt;
ssl_certificate_key /etc/nginx/ssl/WEBSITE/PATH/server.key;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers CIPHER;
ssl_prefer_server_ciphers off;
ssl_dhparam /etc/nginx/dhparams.pem;

add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";

location / {
    proxy_pass             http://127.0.0.1:6001;
    proxy_read_timeout     60;
    proxy_connect_timeout  60;
    proxy_redirect         off;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
}

access_log /home/forge/WEBSITE/so_ac.log;
error_log  /home/forge/WEBSITE/so_er.log error;

}

config.json

{
  "debug": true,
  "port": 6002,
  "appManager.array.apps": [
    {
      "id": "ID",
      "key": "KEY",
      "secret": "SECRET"
    }
  ],
  "ssl": {
        "certPath": "PATH",
        "keyPath": "PATH"
  }
}

Upvotes: 1

Views: 1314

Answers (1)

Jaeger
Jaeger

Reputation: 1716

For the validateWebsocket, it should be

$pusher = new Pusher(env("PUSHER_APP_KEY"), env("PUSHER_APP_SECRET"), env("PUSHER_APP_ID"));
return $pusher->socket_auth($channel_name, $socket_id);

Update #1:

In case you're blocking all of your routes and you would like to use channels.php then you should redirect the request. The issue was that the route was not found due to custom routing that I've implemented that blocked the access.

Place this in your api.php for example, and set the authEndpoint in your Echo configuration to authEndpoint: "/api/broadcasting/auth",

Route::prefix('broadcasting')->group(function () {
    // broadcasting/auth
    Route::post('/auth', [BroadcastController::class, 'authenticate']);
});

For WSS, the only workaround was to connect to WS and then upgrade it to WSS. Any better suggestion is welcome!

Upvotes: 0

Related Questions