8

I am using Laravel Event Broadcast and Pusher to utilize websockets both on my API and Web. If I try them individually, both work fine. What I mean is:

Broadcast::routes(['middleware' => 'web']); // this works for my Laravel website

Broadcast::routes(['middleware' => 'auth:api']); // this works for my api

However, if I want to use both at the same time like this:

Broadcast::routes(['middleware' => ['auth:api', 'web']]); // doesn't work

... it crashes for both, which I suspect that it is assuming I am trying to enable for both auth:api && web middlewares.

Is there a way to use an OR kind of statement for this (auth::api || 'web')? What if I want to use both at the same time and if it passes one middleware, it bypasses the middleware.

Please note that I am using Laravel Passport for my api.


Or is there a way to combine and creating a mixed middleware for both (which will essentially check for either api or web)? So I can use something like this maybe:

Broadcast::routes(['middleware' => 'broadcast']); // or auth:broadcast

Update:

As far as I understand, if I create a new Middleware called broadcast, I can do:

class BroadcastMiddleware() {

  public function handle() {
    $web = Auth::guard('web')->user();
    if ($web) {
        return response()->json($web);
    }

    $api = Auth::guard('api')->user();
    if ($api) {
        return response()->json($api);
    }
    return response()->json('Unauthorized.', 500);
  }
}

But then how do I change /broadcasting/auth route? If I try this:

Route::post('/realtime/auth', function(){
    return true;
})->middleware('broadcast');

This returns the user object info, however instead, it should return something like: auth:"374f7ff42b7da877aa35:c29addedec281b418331a61dc3cfc74da8b108222565fa4924a8..."

5 Answers 5

13

Why not just use something like this in the BroadcastServiceProvider? This creates two separate endpoints with separate middleware assigned.

    Broadcast::routes(['middleware' => 'web']);

    Broadcast::routes(['prefix' => 'api', 'middleware' => 'api']);
Sign up to request clarification or add additional context in comments.

4 Comments

Great solution, used this myself. Although I had to specify the middleware as 'auth:api' to get it to work. Thanks!
@Sledmore glad I could help!
This seems waaaay more elegant than my solution. I didn't try it myself personally just yet though.
this works and still valid even on L11 2024
4

I finally figured out how to do it.

I am not sure if it is the best way of achieving this, and I'd highly appreciate any improvements.

How I achieved is created a new middleware for 'web' and left the other one as it it. Here are the steps.

1) In 'BroadcastServiceProvider', left only auth:api guard for Broadcast::routes(['middleware' => 'auth:api']);.

This way, Laravel's auth:api method for authenticating broadcasting works as expected.

2) Created a middleware called "Broadcast" and mapped it in Kernel.php like so:

'broadcast' => \App\Http\Middleware\Broadcast::class

and the Broadcast.php middleware looks like this:

public function handle($request, Closure $next)
{
    $web = Auth::guard('web')->user();
    if ($web) {
        return response()->json(\Illuminate\Support\Facades\Broadcast::auth($request));
    }

    return response()->json('Unauthorized.', 500);
}

3) Created a unique route other than Laravel's /broadcasting/auth in my routes>web.php

Route::post('/guard/broadcast/auth', function(\Illuminate\Support\Facades\Request $req){
    return true;
})->middleware('broadcast');

4) And then only on my blade, I use it like so:

<script>

let pusher = new Pusher("{{ env('PUSHER_APP_KEY') }}", {
    cluster: 'us2',
    encrypted: true,
    auth: {
        headers: {
            'X-CSRF-TOKEN': "{{ csrf_token() }}"
        }
    },
    authEndpoint: '{{ env('APP_URL') }}' + '/guard/broadcast/auth',
});

let channel = pusher.subscribe('private-channel.{{ Auth::user()->id }}');

channel.bind('my-event', addMessage);

function addMessage(data) {
    console.log(data);
}

</script>

Comments

1

I'm preferable just using middleware that extends to both auth:api and web middlewares.

like what I posted in here: https://github.com/tlaverdure/laravel-echo-server/issues/266#issuecomment-365599129. So, I just maintenance 1 middleware if I wanted to change it in the future

1 Comment

But, this approach didn't return me auth:"374f7ff42b7da877aa35:c29addedec281b418331a61dc3cfc74da8b108222565fa4924a8..." which is what the authenticator needs
1

BroadcastServiceProvider

if (request()->hasHeader('authorization')){
    Broadcast::routes(['middleware' => 'auth:api']);
} else {
    Broadcast::routes();
}

Comments

0

It is better to use prefix approach for achieve multiple authorization types. If you will use a middleware - it is just redundant middleware. If you will use if block (as on a code snippet below): you will face problem with routes caching, it will return 403 error becuase Laravel should cache a route with a set of middlewares.

if (request()->hasHeader('authorization')){
    Broadcast::routes(['middleware' => 'auth:api']);
} else {
    Broadcast::routes();
}

You even may register separate service providers for web and api to split responsibilities and it will work. For Web

class BroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes(['middleware' => ['web']);

        require base_path('routes/channels.php');
    }
}

And for Api

class ApiBroadcastServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     *
     * @return void
     */
    public function boot()
    {
        Broadcast::routes(['prefix' => 'api', 'middleware' => ['auth:api']]);

        require base_path('routes/dam-channels.php');
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.