Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Adgower's avatar
Level 14

Laravel Breeze api: private channels

I have installed laravel breeze --api, setup user auth working for seperate vue 3 api. I installed echo etc, and got public websocket broadcasting working. when I switch it to a private channel. It returns 401 unauthorized.

window.Echo = new Echo({
  broadcaster: "pusher",
  key: process.env.PUSHER_APP_KEY,
  cluster: process.env.PUSHER_APP_CLUSTER,
  wsHost: window.location.hostname,
  wsPort: 6001,
  wssPort: 6001,
  encrypted: false,
  forceTLS: false,
  enabledTransports: ["ws", "wss"],
  disableStats: true,
  authEndpoint: process.env.API + "/broadcasting/auth",
  auth: {
    headers: {
      accept: "application/json",
    },
  },
});
const channel = window.Echo.private("private.test.1");
  channel
    .subscribed(() => {
      console.log("subscribed");
    })
    .listen(".test", (e) => {
      console.log(e);
      Notify.create({
        message: e.message,
        type: "positive",
      });
    });
class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes(['middleware' => ['auth:sanctum']]);

        require base_path('routes/channels.php');
    }
}
Broadcast::channel('private.test.{id}', function ($id) {
    return true;
});
public function broadcastOn()
    {
        return new PrivateChannel('private.test.1');
    }

    public function broadcastAs()
    {
        return 'test';
    }

    public function broadcastWith()
    {
        $faker = \Faker\Factory::create();

        return [
            'message' => $faker->sentence,
        ];
    }
class TestEventCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'test:event';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        event(new TestEvent());

        return Command::SUCCESS;
    }
}

I have authenticated the user in the vue app

import { defineStore } from "pinia";
import { Cookies, Loading, Notify } from "quasar";
import { api } from "src/boot/axios";

export const useAuthStore = defineStore("auth", {
  state: () => ({
    isAuthentictated: Cookies.has("user") ? true : false,
    user: Cookies.has("user") ? Cookies.get("user") : null,
  }),

  actions: {
    login(data) {
      Loading.show();

      // CSRF token
      api
        .get("/sanctum/csrf-cookie")
        .then(() => {
          // Login
          api
            .post("/login", data)
            .then((response) => {
              this.isAuthentictated = true;

              // get user
              api.get("/api/user").then((response) => {
                // set user cookie 2hrs
                Cookies.set("user", response.data, {
                  expires: "2h",
                });

                this.user = response.data;

                Loading.hide();

                Notify.create({
                  message: "You are now logged in",
                  type: "positive",
                });

                this.router.push({ name: "dashboard" });
              });
            })
            .catch((error) => {
              console.log(error);
              Loading.hide();
            });
        })
        .catch((error) => {
          console.log(error);
          Loading.hide();
        });
    },

    logout() {
      Loading.show();

      api
        .post("/logout")
        .then((response) => {
          this.isAuthentictated = false;
          Cookies.remove("user");
          Loading.hide();

          Notify.create({
            message: "You are now logged out",
            type: "positive",
          });

          this.router.push({ name: "login" });
        })
        .catch((error) => {
          Loading.hide();
        });
    },
  },
});

possible scenarios/references I'm trying:

https://stackoverflow.com/questions/65437196/laravel-echo-websockets-private-channels/65444032#65444032

https://stackoverflow.com/questions/72551784/laravel-9-sanctum-login-with-fetch-api-not-working

https://github.com/beyondcode/laravel-websockets/issues/386

https://github.com/laravel/echo/issues/342

https://github.com/laravel/echo/blob/a26aed58896baeb848bc1172758a51065d9b1e14/src/connector/connector.ts

https://stackoverflow.com/questions/45658149/laravel-echo-pusher-authentication-fails-403

https://laracasts.com/discuss/channels/laravel/laravel-echo-server-with-sanctum

https://www.youtube.com/watch?v=rzZoswkfi90&list=PLSfH3ojgWsQosqpQUc28yP9jJZXrEylJY&index=51

https://gist.github.com/sdwru/2fc0cd414b12cabfb3b84d05bb693375

https://laracasts.com/discuss/channels/laravel/laravel-echo-websockets-private-channels

Any tips?

0 likes
1 reply

Please or to participate in this conversation.