LaravelのPUSH通知を独自認証したプライベートなチャンネルで受け取る

Laravel のPUSH 通知を独自の認証機構を持ったプライベートなチャンネルでやりとりするまでの実装手順をまとめました。
・独自の認証ルート定義
・独自の認証機構定義
・チャンネルのプライベート化(サーバー/クライアント両方)
が必要です。
※前提条件としてPUSH通知用のドライバとしてPusherを、PUSHサーバーとしてLaravel WebSockets を利用しています。

認証ルート定義

Laravel公式ドキュメント: Laravel 5.7 ブロードキャスト: 認証ルート定義
https://readouble.com/laravel/5.7/ja/broadcasting.html#defining-authorization-routes
上記のドキュメントに従い、PUSHクライアントを認証するためのルーティングを設定します。デフォルトですと

// app/Providers/BroadcastServiceProvider.php
class BroadcastServiceProvider extends ServiceProvider
{
    ...
    public function boot()
    {
        Broadcast::routes();
        ...
    }
}

として、Broadcast::routes で定義されています。ですが、LaravelEchoクライアントがPUSH通信の認可に使用するエンドポイントは独自に定義、設定できます。なので、認可のための独自のルーティングをルーティングファイルに設定し、さらに独自の認証機構も組み込みましょう。
※APIサーバーにて認可させるため、api.phpに追加し、さらに認証用の独自ミドルウェアを設定しています

// routes/api.php
// push/auth への POST を
// 独自の認証ミドルウェア push.auth で認証したうえで
// PushController の auth アクションで認可させる
Route::group(['middleware' => 'push.auth'], function () {
    Route::group(['prefix' => 'push'], function () {
        Route::post('auth', 'PushController@auth');
    });
});

認証ミドルウェアの実装

こちらは通常のミドルウェア同様に Kernel.php のミドルウェアテーブルに追加したうえで、実装してください

// app/Http/Kernel.php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
    ...
    protected $routeMiddleware = [
        'auth' => \App\Http\Middleware\Authenticate::class,
        ...
        'push.auth' => \App\Http\Middleware\PushAuthenticate::class,
        ...
    ];
    ...
}
// app/Http/Middleware/PushAuthenticate.php
<?php

namespace App\Http\Middleware;

class PushAuthenticate
{
...
    public function handle($request, Closure $next)
    {
        $key = $request->input('key');
        // do something authentication
        ...
        return $next($request);
    }
}

認可のエンドポイント実装

BroadcastingController の auth アクションと同様の実装を行います。Pusherの auth の結果をJSONで返すだけでよいです。

// app/Http/Controllers/PushController.php

class PushController extends BaseController
{
    public function auth(Request $request, Broadcaster $broadcaster)
    {
        // pusher用の認証情報 $key, $secret, $appIdを取得する
        ...
        // pusher の認証を行い、その結果を返す
        $pusher = new Pusher($key, $secret, $appId);
        $auth = $pusher->presence_auth(
            $request->input('channel_name'),
            $request->input('socket_id'),
            'xxx');
        $auth = json_decode($auth);
        return response()->json($auth);
    }
}

LaravelEcho 側に認可用エンドポイント設定

特に何もしなければLaraveEchoのクライアントは /broadcasting/auth エンドポイントで認証を行うため、authEndpoint オプションを設定、認証用のエンドポイントを変更します。Laravel 標準の auth を使わず独自認証を使うため、クライアントからの認証キーをURLに含めて送らせ認証させています

// resoutes/js/bootstrap.js
...
window.Echo = new Echo({
    broadcaster: 'pusher',
    // 認証情報としてクライアントからクエリストリングでキーを送る
    // key はクライアント側に適宜定義する
    authEndpoint: '/api/push/auth?key=' + key,
    ...    
});

LaravelEchoクライアントからのlisten時にプライベートチャンネルを指定

Laravel公式ドキュメント: Laravel 5.7 ブロードキャスト: イベントのリッスン のプライベートチャンネルのイベントをリッスンしたい場合は~に従い下記のように書き換えます。
https://readouble.com/laravel/5.7/ja/broadcasting.html#listening-for-events

// 修正前
Echo.channel('channel').listen('Event', e => {...});
// 修正後
Echo.private('channel').listen('Event', e => {...});

Laravel の PUSH 機能を使ったシステム構築をお考えなら

 宮城、仙台に限らず、PUSH機能を使ったシステム導入にお困りの方や、システムの構築可能なベンダーをお探しならば、ぜひ弊社までご相談ください。

宮城県仙台市のシステム開発会社FITS
https://www.fits-inc.jp/