I'm trying to build a Real-Time using Laravel websockets + Passport for authentication as backend and Flutter as frontend.
In public channel it work as it should do, but in private channel it always give 403 Forbidden error when trying to connect …
This is the backend code:
The event:
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Str;
class messageEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user_id, $message, $chat_id;
public function __construct($user_id, $chat_id, $message)
{
$this->user_id = $user_id;
$this->chat_id = $chat_id;
$this->message = $message;
}
public function broadcastWith()
{
return [
'user_id' => $this->user_id,
'message' => $this->message,
'chat_id' => $this->chat_id,
];
}
public function broadcastOn()
{
return new PrivateChannel('chat.' . $this->user_id);
}
}
BroadcastServiceProvider.php
file:
<?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:api']]);
require base_path('routes/channels.php');
}
}
Channel.php
file:
<?php
use Illuminate\Support\Facades\Broadcast;
/*
|--------------------------------------------------------------------------
| Broadcast Channels
|--------------------------------------------------------------------------
|
| Here you may register all of the event broadcasting channels that your
| application supports. The given channel authorization callbacks are
| used to check if an authenticated user can listen to the channel.
|
*/
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
Broadcast::channel('chat.{id}', function ($user, $id) {
return $user->id == $id;
});
And this is the passport access-token I'm trying to use (it's for user with id = 1):
[![enter image description here][4]][4]
For Flutter I'm using the Laravel-echo package from this repo: Laravel-echo
and this is a simple similar code:
import 'package:flutter/cupertino.dart';
import 'package:laravel_echo/laravel_echo.dart';
import 'package:pusher_client/pusher_client.dart';
import 'package:flutter/material.dart';
void main() {
runApp(Chat());
}
class Chat extends StatefulWidget {
const Chat({Key? key}) : super(key: key);
@override
State<Chat> createState() => _ChatState();
}
class _ChatState extends State<Chat> {
@override
void initState() {
super.initState();
print('called');
Future.delayed(Duration.zero).then((value) {
const String PUSHER_KEY = 'ssss';
const String BEARER_TOKEN =
'Backend token for user id = 1 ';
const String AUTH_URL = 'http://192.168.43.113:8000/broadcasting/auth';
PusherOptions options = PusherOptions(
host: '192.168.43.113',
encrypted: false,
wsPort: 6001,
//wssPort: 6001,
//host: AUTH_URL,
auth: PusherAuth(
AUTH_URL,
headers: {
'Authorization': 'Bearer $BEARER_TOKEN',
'apiKey':
'THSzx8cmJny4DFmjvjX2calOKSduaJxb3YKC9sCuoCdEiF4J9w6qul5kRFwt1mUR'
},
),
);
// Create pusher client
PusherClient pusherClient = PusherClient(
PUSHER_KEY,
options,
autoConnect: false,
enableLogging: true,
);
// Create echo instance
Echo echo = Echo(
broadcaster: EchoBroadcasterType.Pusher,
client: pusherClient,
);
// Listening public channel
echo.private('chat.1').listen('messageEvent', (e) {
print(e.data);
});
// Accessing pusher instance
echo.connector.pusher.onConnectionStateChange((state) {
print(state!.currentState.toString());
});
});
}
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: Text('Chat'),
),
),
);
}
}
Hope someone can save me :)