So, as my title says, I want to change Laravel's default Broadcast
auth middleware to a custom auth middleware that I made which uses token-based authentication. I made this because my app is an API-based app, and, when a user authenticates, I create a session token and send it to him and also store it inside the DB with an expires_at
column.
I am using Pusher
.
I have the following middleware:
class AuthCustom
{
public function handle($request, Closure $next)
{
// if we have the session token stored in header
if ($request->header('x-session')) {
$session = Session::where('id', $request->header('x-session'))->where('expires_on', '>=', date('Y-m-d G:i:s'))->with('user')->first();
if ($session !== null) {
$user = (new User())->where('id', $session->user_id)->first();
if ($user !== null) {
$request->merge(['user' => $user]);
return $next($request);
}
}
}
}
My BroadcastServiceProvider
code is as follows:
class BroadcastServiceProvider extends ServiceProvider
{
public function boot()
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}
If I put Broadcast::routes(['middleware' => 'authcustom']);
in BroadcastServiceProvider
, the boradcasting/auth
gives a 403
status code because $request->user()
is null, which then results in an Access forbidden
.
I have tried searching the whole damn web, and I found nothing about changing the default auth middleware for broadcasting.
I even tried removing Broadcast::routes()
and customizing a new route /broadcast
which returned a Pusher
socket_auth
object and everytime I got a 419 Unkown
status code.
Any ideas or maybe you can point me in the direction where I could manage this? Thank you!
Later edit: My JS Echo connection looks like this:
Vue.use(VueEcho, {
broadcaster: 'pusher',
key: 'xxxxxxxxxxxxxx',
cluster: 'eu',
authEndpoint: 'http://localhost/api.easycargo.ro/public/broadcasting/auth',
auth: {
headers: {
'x-session': this.auth.token
}
}
});
I'm glad you got something working. For later readers, here's a more Laravel-esque way to solve the problem in the question: create a custom auth guard used to authenticate requests for the special routes.
Laravel's AuthManager
includes a helper method—viaRequest()
—that simplifies the creation of a Guard
that authenticates a user with data from the request context without the need to fully-implement Illuminate\Contracts\Auth\Guard
. We can bind our custom guard in the boot()
method in AuthServiceProvider.php:
public function boot()
{
Auth::viaRequest('custom-auth', function ($request) {
// Any custom user-lookup logic here. For example:
if ($request->header('x-session')) {
$user = // ...try to fetch a user...
return $user;
}
});
}
As we can see, we just pass a closure to the viaRequest()
method that returns a User
object when authentication succeeds, or null
when authentication fails.
Next, we'll tell Laravel about our new auth guard by adding an entry to the 'guards'
array in config/auth.php:
'guards' => [
...
'broadcasting' => [
'driver' => 'custom-auth',
],
],
Finally, we need to update the middleware for any routes that should authenticate a user with our custom Guard
. We can use Laravel's built-in auth middleware and specify which guard to apply as a middleware parameter. For example, we'll initialize the broadcasting routes in the question's BroadcastServiceProvider.php:
Broadcast::routes([ 'middleware' => [ 'auth:broadcasting', ... ] ]);
...where broadcasting
matches the name we assigned to our custom Guard
in config/auth.php.
This approach enables us to use all of Laravel's Auth
services, provides a more central place to define our authentication logic, and simplifes automated testing because we can more easily mock up authentication as needed.
I actually managed to find a solution, so all I needed to do was bind the $user
that I got in my custom auth
middleware to the request by doing the following thing:
$request->merge(['user' => $user]);
//add this
$request->setUserResolver(function () use ($user) {
return $user;
});
and now $request->user()
which laravel checks returns the user object and passes the validation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With