PrivateChannel 403 error Laravel Echo Pusher Laravel Websockets local setup - laravel

I am getting a 403 on broadcasting/auth route.
I am using Laravel websockets package for web sockets and I have the below setup
- Backend Laravel server ( on port 8000 )
- Laravel Websockets Server ( laravel is running on 8001 and websocket server on 6001 )
- Standalone Ionic React app ( on port 8100)
Now everything works when I am trying Public Channel but when I try Private Channel it fails.
in the above screenshot of Laravel sockets dashboard I can see connection made as this is the same socketId which went with the request.
I am using Laravel Sanctum for Authentication.
PFB :- my client side code
const headers = {
'Content-Type': 'application/json',
Authorization: window.localStorage.getItem('token')
? `Bearer ${window.localStorage.getItem('token')}`
: '',
'Access-Control-Allow-Credentials': true,
};
const options = {
broadcaster: 'pusher',
key: 'abcsock',
authEndpoint: 'http://localhost:8001/api/broadcasting/auth',
authorizer: (channel, options) => {
return {
authorize: (socketId, callback) => {
axios
.post(
'http://localhost:8001/api/broadcasting/auth',
{
socket_id: socketId,
channel_name: channel.name,
},
{ headers, withCredentials: true }
)
.then((response) => {
callback(false, response.data);
})
.catch((error) => {
callback(true, error);
});
},
};
},
wsHost: '127.0.0.1',
wsPort: 6001,
encrypted: true,
disableStats: true,
enabledTransports: ['ws', 'wss'],
forceTLS: false,
};
Code from Laravel Websockets Server
api.php file
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Broadcast;
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
return $request->user();
});
Broadcast::routes(['middleware' => ['auth:sanctum']]);
BroadcastServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Broadcast::routes(['middleware' => ['auth:sanctum']]);
require base_path('routes/channels.php');
}
}
NewNotification.php
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\BroadcastMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Broadcasting\PrivateChannel;
use App\AppNotification;
use App\User;
class NewNotification extends Notification
{
use Queueable;
public $notification;
public $user;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(AppNotification $notification, User $user)
{
$this->notification = $notification;
$this->user = $user;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['database', 'broadcast'];
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
$notification = $this->notification;
return [
'id' => $notification->id,
'title' => $notification->title,
'description' => $notification->description,
'button_text' => $notification->button_text,
'is_read' => $notification->is_read,
'created_at' => $notification->created_at,
[
'notification_for' => $notification->notifiable
]
];
}
public function toBroadcast($notifiable)
{
return new BroadcastMessage($this->toArray($notifiable));
}
public function broadcastOn()
{
return new PrivateChannel('Notifications.' . $this->user->id);
}
}
channels.php
<?php
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('Notifications.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
}, ['guards' => ['sanctum']]);
I have attached whatever I felt was sufficient to explain the issue and for you to troubleshoot but if you need anything more please ask.
Any help will be appreciated

i liked this package because its wrote in php but its sortof abandon and a lot of issues that not solved.
alternative of this server is laravel-echo-server(as laravel docs recommends) very easier to use.
https://stackoverflow.com/a/61704796/7908390 more info if you can work with laravel-sockets im glad to see a new example

Have you added authentication for your channels.php? Please refer here:
https://laravel.com/docs/7.x/broadcasting#defining-authorization-routes
What does it look like?
I think you are doing everything correctly but you have not authorized your routes.

I had the similar error with Laravel & pusher.
I have fixed using decodeURIComponent and moving BroadCast::routes(['middleware' => ['auth:sanctum']]) to routes/api.php from BroadcastServiceProvider.php
Also, add withCredentials = true.
const value = `; ${document.cookie}`
const parts = value.split(`; XSRF-TOKEN=`)
const xsrfToken = parts.pop().split(';').shift()
Pusher.Runtime.createXHR = function () {
const xhr = new XMLHttpRequest()
xhr.withCredentials = true
return xhr
}
const pusher = new Pusher(`${process.env.REACT_APP_PUSHER_APP_KEY}`,
{
cluster: 'us3',
authEndpoint: `${process.env.REACT_APP_ORIG_URL}/grooming/broadcasting/auth`,
auth: {
headers: {
Accept: 'application/json, text/plain, */*',
'X-Requested-With': 'XMLHttpRequest',
'X-XSRF-TOKEN': decodeURIComponent(xsrfToken)
}
}
})
I hope this helps a bit.

Related

Laravel echo private channel not working on Nuxt js

I am using Laravel 9, Nuxt js, laravel-websocket. Laravel Echo is working only on public channels not working on private channels.
Here is my code.
channels.php
Broadcast::channel('trades', function ($user) {
return auth()->check();
});
Events file (NewTrade.php)
class NewTrade implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $trade;
public $user;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($trade, User $user)
{
$this->trade = $trade;
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('trades');
}
}
nuxt.config.js
buildModules: [
['#nuxtjs/laravel-echo', {
broadcaster: process.env.BROADCAST_DRIVER,
key: process.env.PUSHER_APP_KEY,
cluster: process.env.PUSHER_APP_CLUSTER,
forceTLS: false,
wsHost: '127.0.0.1',
wsPort: 6001,
wssPort: 6001,
disableStats: true,
authModule: true,
connectOnLogin: true,
encrypted: true,
authEndpoint: process.env.PUSHER_AUTH_ENDPOINT,
}]
],
echo.js (Plugin)
import Pusher from "pusher-js";
Pusher.logToConsole = true;
client echo
this.$echo.private('trades')
.listen('NewTrade', (e) => {
console.log("A testing");
});
Note: If I send data from the public channel client-side received it but the only problem is when I broadcast on the private channel.
I have spent more than 10 hours and tried everything I could, but no luck. :(
Thanks.

Installing fortify /bootstrap in new laravel 8 app I got error

I need to install fortify /bootstrap in the new laravel eight app
and running the home page, I got an page with message (https://prnt.sc/22sllw5) /error message :
Two Factor Authentication
Recovery Codes:
WW9rE3LNFi-h5knxwle2v
43nN0mxYVy-4p5lLHFcCD
....
“Disable” button
If in config/fortify.php I have :
'limiters' => [
'login' => 'login',
'two-factor' => 'two-factor',
],
'views' => true,
'features' => [
Features::registration(),
],
Also I modified app/Providers/FortifyServiceProvider.php :
<?php
namespace App\Providers;
use App\Actions\Fortify\CreateNewUser;
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Fortify;
class FortifyServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Fortify::createUsersUsing(CreateNewUser::class);
Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
Fortify::registerView(function () {
return view('auth.register');
});
Fortify::loginView(function () {
return view('auth.login');
});
RateLimiter::for('login', function (Request $request) {
$email = (string) $request->email;
return Limit::perMinute(5)->by($email.$request->ip());
});
RateLimiter::for('two-factor', function (Request $request) {
return Limit::perMinute(5)->by($request->session()->get('login.id'));
});
}
}
In routes/web.php :
Route::get('/', function () {
return view('welcome');
});
Route::view('/home', 'home')->middleware(['auth', 'verified']);
How can I fix it?
I want some simple decisions, as I do not some complicated register/login functionality...
Thanks in advance!

Laravel pusher/echo getting broadcast error 500 and 403

Hello I'm trying to make chat system for my app but I'm having problem making pusher and echo work. When I open my Chat between 2 people it does not update in real time and I have to refresh the page in order to get the updated stuff like messages and such. In console I'm getting these 2 errors
POST http://localhost/broadcasting/auth 403 (Forbidden)
POST http://localhost/broadcasting/auth 500 (Internal Server Error)
bootstrap.js
import Echo from 'laravel-echo';
window.Pusher = require('pusher-js');
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
encrypted: true,
});
ChatBroadcast.php
class ChatBroadcast implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $ticket;
/**
* Create a new event instance.
*
* #param $ticket
*/
public function __construct(Ticket $ticket)
{
$this->ticket = $ticket;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('tickets_channel.' . $this->ticket->id);
}
public function broadcastWith(){
$messages = Message::all()->where('ticket_id','=',$this->ticket->id)->sortBy('created_at');
return [
'ticket' => $this->ticket,
'messages' => $messages
];
}
}
channels.php
use App\Ticket;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('tickets_channel.{ticketID}', function ($user, $ticketID) {
Auth::check();
$ticket = Ticket::all()->where('id', '=', $ticketID)->first();
return $ticketID == $ticket->id;
});
VueComponent
mounted() {
Echo.private('tickets_channel.${ticketID}')
.listen('ChatBroadcast', (e) => {
console.log(e);
this.messagesMutable = e.messages;
this.state = e.ticket.isOpened;
});
},
This is my log for 500 error
[2020-09-08 09:25:24] local.ERROR: Invalid channel name private-tickets_channel.${ticketID} {"userId":11,"exception":"[object] (Pusher\\PusherException(code: 0): Invalid channel name private-tickets_channel.${ticketID} at /Users/miroslavjesensky/Documents/Blog/vendor/pusher/pusher-php-server/src/Pusher.php:282)
-EDIT-
I have managed to fix the 500 error by changing VueComponent code to this
mounted() {
let id = this.ticket.id;
Echo.private('tickets_channel' + id)
.listen('ChatBroadcast', (e) => {
this.messagesMutable = e.messages;
this.state = e.ticket.isOpened;
});
},
Turns out the problem was with another VueComponent I am using with the first one. After fixing the listening part of echo there aswell all works as it should

Laravel does not check the authorization when attempting to subscribe a private channel

I have newly started working with laravel broadcasting and faced a problem. I am using Pusher and I want to check if users are authorized to subscribe to a private channel. Users' access to posts' comment notification is authenticated but not authorized. I am trying to send notification of new comment only to the post's author but all authenticated users who have opened the post get notifications. Am I missing something or what?
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class NewCommentEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public $comment;
public function __construct($comment)
{
$this->comment = $comment;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('post-'.$this->comment->post_id);
}
public function broadcastAs()
{
return 'new-comment-event';
}
public function broadcastWith()
{
return ['comment' => $this->comment->comment];
}
}
routes/channel.php:
<?php
use App\models\Post;
Broadcast::channel('App.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('post-{id}', function ($user, $id) {
return false;
//return $user->id == Post::find($id)->author_id;
});
And the JavaScript in view:
var pusher = new Pusher('904d58ankty8c8397d000', {
authEndpoint: 'http://localhost/blog/public/broadcasting/auth',
cluster: 'ap2',
forceTLS: true,
auth: {
headers: {
'X-CSRF-Token': "{{csrf_token()}}"
}
}
});
var privateChannel = pusher.subscribe("private-post-{{{$post->id}}}");
privateChannel.bind('new-comment-event', function(data) {
$('#post-comments').append('<p>'+data.comment+'</p>');
});
By the way the following is the provider code:
public function boot()
{
Broadcast::routes(['middleware' => ['auth']]);
require base_path('routes/channels.php');
}
The laravel version i am using is: 5.8
What does "$this->comment->post_id" denote? If it denotes the id of that particular post, then who ever has access to that post will get the notification. Get author_id from post_id and Broadcast on 'post-'.author_id.

Laravel Echo 500 error not receiving pusher event

i had a problem when using presence channel in Laravel Echo with pusher. when I fire an event, i get 500 error from BroadcastException without the response body which is hard for me to debug it. when i look to pusher debug console, the presence event was listened by pusher. so i assume my event has never been fired to Pusher. Here is the preview in my network tab
my controller:
public function store() {
$user = auth()->user();
$message = $user->messages()->create([
'message' => request('message')
]);
event(new MessageReceived($message, $user));
return ['status' => 'OK'];
}
the MessageReceived class
namespace App\Events;
class MessageReceived implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
public $user;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Message $message, User $user)
{
$this->message = $message;
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return new PresenceChannel('chatroom');
}
}
and here is my vuejs
mounted() {
axios.get('/messages')
.then(response => {
this.messages = response.data
})
.catch(error => {
console.log(error)
})
Echo.join('chatroom')
.listen('MessageReceived', (e) => {
console.log(e) //never get into this
})
},
i can't find where the error is. i use cluster ap1 and is declared in broadcasting.php and in my bootstrap.js. anyone can help me out?
This can be caused by an error in your configuration. Here are some things to check:
In your .env file, make sure the pusher id, key, and secret are correctly set.
If you upgraded from Laravel 5.3 to Laravel 5.4, note that the .env variables PUSHER_KEY is now PUSHER_APP_KEY and PUSHER_SECRET is now PUSHER_APP_SECRET
In your config/broadcasting.php, make sure the cluster is set correctly.
If you are not in HTTPS, you may have to set the 'encrypted key to false
'options' => [
'cluster' => 'ap1', // change this to your app's cluster
'encrypted' => false,
],

Resources