title: Laravel Echo + Websockets + Private Channels
body: <p>I know I'm not the first struggling with this. But after some days and going trough a lot of related questions i somehow feel that my case deserves it's own question :).</p>
  <p>I have a working websocket solutions with Laravel Websockets (<a href="https://beyondco.de/docs/laravel-websockets/getting-started/introduction" rel="nofollow noreferrer">https://beyondco.de/docs/laravel-websockets/getting-started/introduction</a>) and Laravel Echo for public channels.
  My client application is a vue-cli app and connects to the server + broadcast messages on public channels work great. The authorization is handled by Laravel Passport. So through sending a Bearer token in the Authorization header the backend application knows if the user is authenticated.</p>
  <p>However I'm struggling to get Private channels to work. Trying to authenticate always gives me this error:</p>
  <pre><code>Access to XMLHttpRequest at 'https://my-app.test/broadcasting/auth' from origin 'https://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
  </code></pre>
  <p>I know this CORS error comes on my way when I have a server issues so I tried debugging the request in Insomnia. However when mimicking the request in Insomnia it gives a response 200 and also what would be expected:</p>
  <p><a href="https://i.stack.imgur.com/ctPuB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ctPuB.png" alt="Mimick auth request in Insomnia" /></a></p>
  <p>I've been reading several guides and stackoverflow questions but I can't find anything similar.
  Going back to it might be a CORS issues but I don't think that is the case. My OPTIONS request returns back just fine.</p>
  <p>To be complete I also add some code that might help in debugging.</p>
  <p>My BroadcastServiceProvider</p>
  <pre><code>public function boot()
  {
      Broadcast::routes(['middleware' =&gt; ['auth:api']]);
  
      require base_path('routes/channels.php');
  }
  </code></pre>
  <p>My channels.php</p>
  <pre><code>use Illuminate\Support\Facades\Broadcast;
  
  Broadcast::channel('App.User.{id}', function ($user, $id) {
      return (int) $user-&gt;id === (int) $id;
  });
  </code></pre>
  <p>The client</p>
  <pre><code>this.echoClient = new Echo({
    broadcaster: 'pusher',
    key: process.env.VUE_APP_WEBSOCKETS_APP_ID,
    wsHost: process.env.VUE_APP_WEBSOCKETS_URL,
    wssPort: 6001,
    // forceTLS: true,
    disableStats: true,
    authEndpoint: process.env.VUE_APP_SERVER_URL + '/broadcasting/auth',
    auth: {
      headers: {
        Authorization: &quot;Bearer &quot; + this.$store.state.auth.auth_token
      }
    }
  })
  
  // this one works!!
  this.echoClient.channel('App.User')
    .listen('UpdatePosts', (e) =&gt; {
      console.log('event received')
      console.log(e)
    })
  
  // private channels don't work ... :'(
  this.echoClient.private('App.User.' + this.user.id)
    .listen('UpdatePosts', function(e) {
      console.log(e)
    })
  </code></pre>