📝

Laravel 8のログアウト後のリダイレクト先を設定 - Laravel Fortify - 謎である

2021/10/02に公開

ログアウトでHTTPステータス 403 Forbiddenの発生

サブディレクトリ配下で、Laravel JetStream + Inertia で利用してみる。
app.urlや、asset_urlを調整したり、bladeの調整などを行いながら、画面遷移の不備を一つ一つつぶしていく。

ログアウト後、403 Forbiddenが発生する。
認証は破棄されているため、ログアウト処理はできているらしい。
つまり、ログアウト後の遷移先がおかしい、というのが原因としてもっとも可能性が高い。

サブディレクトリ配下で動かしているので、それに関する調整が必要なのだろうが、どのように調整すれば良いのか分からない。

結論

設定方法 1

公式ドキュメントのLaravel 8.x Laravel Fortify リダイレクトのカスタマイズにログアウト後のリダイレクト先のカスタマイズ方法が記載されている。
本家ドキュメントの解説も同じ

例えば、以下のように設定することで、ログアウト後、ログイン画面に遷移する。

app/Providers/FortifyServiceProvider.php
use Laravel\Fortify\Contracts\LogoutResponse;public function register()
    {
        $this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
            public function toResponse($request)
            {
                return redirect('/login');
            }
        });
    }

設定方法 2

ソースをトレースしていて気が付いたが、fortify.phpへの設定記述でも対応できた。

fortify.phpに、redirects設定として、以下の内容を追記する。

config/fortify.php
    'redirects' => [
        'logout' => config('app.url') . '/login'
    ],

これで、設定方法 1 と同様にログイン画面にリダイレクトされる。(.envAPP_URLの設定も必要)

ただし、この方法はドキュメントに記載がないようだったので、使用するべきかは要検討か。

ドキュメント上では、設定方法 1 を行いましょうとしか記載がない。
config側で設定するのも良いと思うが、環境にも依存しないし変更可能性も低いものなので、config側の設定方法も用意したけど、あえてconfigで設定する方法は紹介しない、ということなのか。謎である。

参考:設定方法 2 にたどり着くまでメモ

(いつもルートの確認のことを失念したままいきなりソースを追い始めるので、戒めとして整理)

とりあえず関連するルートの確認

laradock@1ab70ca27043:/var/www/example-app02$ php artisan route:list

関連するキーワードlogoutを探す

laradock@1ab70ca27043:/var/www/example-app02$ php artisan route:list | grep logout
|      | POST   | logout  | logout  | Laravel\Fortify\Http\Controllers\AuthenticatedSessionController@destroy | web

該当のActionの処理を確認

AuthenticatedSessionControllerクラスのdestroyメソッドの処理を確認
IDEの機能を使って実態クラスを特定
Laravel\Fortify\Http\Responses\LogoutResponse

このクラスが、設定方法 1 を行わなかった際に、同名のインターフェースを通じてインスタンス化される模様。

LogoutResponseの実際の処理

以下が該当の処理のよう。

vendor\laravel\fortify\src\Http\Responses\LogoutResponse.php
    public function toResponse($request)
    {
        return $request->wantsJson()
                    ? new JsonResponse('', 204)
                    : redirect(Fortify::redirects('logout', '/'));
    }

そして、Fortify::redirects()の処理内容が以下。

vendor\laravel\fortify\src\Fortify.php
    public static function redirects(string $redirect, $default = null)
    {
        return config('fortify.redirects.'.$redirect) ?? $default ?? config('fortify.home');
    }

ここの config('fortify.redirects.'.$redirect)により、設定方法 2 が標準で利用可能であることが分かる。

まとめ

公式ドキュメントに載っていない方法なのでFortifyServiceProviderregister()で設定することにします(使うなら)。
念のため、Laravelのバージョンは、v8.62.0です。

Laravel Fortifyが奥深そうということが分かったので、機会があれば追ってみようと思った次第。

こんなところで。

Discussion