Filament/Livewireで本番環境のみファイルアップロードが401エラーになる原因と対処法

Filament/Livewireで本番環境のみファイルアップロードが401エラーになる原因と対処法

FilamentPHPを使っていて、本番環境のみファイルアップロードが401エラーになる現象に遭遇したため、備忘録として原因と対策を記事に書き残しておきます。

発生していた問題

本番環境(Nginxリバースプロキシ + Docker構成など)において、Filamentのファイルアップロード(Livewireの一時URL発行)を実行すると、ブラウザ上ではHTTPSでリクエストしているにもかかわらず、401 Unauthorized が返される。※ローカル環境(HTTP)では問題なく動作する。

原因:署名付きURLの「検証失敗」

Filament(Livewire)のアップロード機能は、セキュリティのために「署名付きURL(Signed URL)」を利用します。この署名は、以下の要素を組み合わせて生成されます。

  • プロトコル(http / https)
  • ホスト名(ドメイン)
  • パス
  • 有効期限

なぜ401になるのか?

リバースプロキシ構成では、ブラウザ ↔ Nginx 間は HTTPS ですが、Nginx ↔ PHP(Docker) 間は HTTP で通信されることが一般的です。

このとき、Laravel側でプロキシの信頼設定が正しく行われていないと、Laravelは Nginx が送ってくれる X-Forwarded-Proto: https というヘッダーを無視してしまいます。

結果として:

  1. ブラウザ側:https://... の署名でリクエストを送る。
  2. Laravel側:自分へのアクセスを http://... だと誤認し、HTTPベースで署名を再計算する。
  3. 判定:ハッシュ値が一致しないため、「署名改ざん」とみなされ 401エラー

となります。

解決策:TrustProxiesの設定

Laravel 11以降では、bootstrap/app.php にてプロキシを信頼する設定を追加します。

// bootstrap/app.php

->withMiddleware(function (Middleware $middleware): void {
    // すべてのプロキシを信頼し、X-Forwarded-* ヘッダーを有効化する
    $middleware->trustProxies(at: '*');
})

この設定により、Laravelは「Nginxからの X-Forwarded-Proto ヘッダー」を正しく読み取り、自分へのアクセスが HTTPS であることを認識できるようになります。その結果、サーバー側で計算される署名がブラウザのものと一致し、正常にアップロードが可能になります。

まとめ

  • 本番環境でだけ401が出るなら「署名(Signature)」の不一致を疑う。
  • プロキシ環境下では、PHP側が「今HTTPSで通信している」と正しく認識できているかが重要。
  • TrustProxies の設定を適切に行い、ヘッダーの信頼パスを通すことで解決する。

まずは、ブラウザの検証ツールを使ってどのようなステータスコードが返ってきているかをきちんと見ましょう。401エラーなら署名URLの不一致の可能性が高いです。


補足ポイント

  • AppServiceProvider での URL::forceScheme('https') も併用すると、生成されるURLが確実にHTTPSになるためより安全。
  • Nginx側で proxy_set_header X-Forwarded-Proto https; が設定されていることも前提条件となる。

参考

以下を参考にしていました。

https://github.com/filamentphp/filament/discussions/9243