laravel メール認証(EmailVerification)で認証ボタンを押すと403エラー 本番環境のhttpsでのみ発生


この記事について

今回、初めてのwebアプリケーション作成にあたって、デプロイ後、最後の最後にメール認証で大ハマりしたので備忘録として残しておきます。
このエラーは皆はなぜおきないのだろう?と不思議になるくらい情報が少なかったり、自分にとっては有益でないものばかりでした。
ちなみに最終的に解決に繋がったのはこちらの記事です。

https://laracasts.com/discuss/channels/laravel/hitting-403-page-when-clicking-verify-link-in-email-using-new-laravel-verification-57?page=1

メール認証が本番環境(https)でのみ403エラーになる

題名の通りです。新規ユーザー登録等を行った際に”全ての機能を利用するためにはメール認証が必要”というwebサービスでよくある機能を"EmailVerification"というlaravel標準のパッケージを利用して実装しました。
開発環境では届いたメールの認証ボタンを押すと、問題なく認証される(localhost:8000)のですが、本番環境のherokuでは認証されず403エラー。ちなみにお名前.comにて独自ドメインを取得しており、heroku内でGUIにてSSL証明書も発行済みです。

さっさと結論

とりあえず結論としては私の場合は下記のようにMiddlewareのTrustProxies.phpで2点変更する事で解決しました。

TrustProxies.php

protected $proxies = '*';

protected $headers = Request::HEADER_X_FORWARDED_AWS_ELB;

※ laravelのバージョンによっては $proxies='**'; とする必要があるみたいです。
 IPを指定する方法もあるみたいです。
 後、未確認ですが $headers の方は変更しなくても大丈夫かもしれません。

考察

改めてheroku logs等で403エラー部分を確認してみると、httpsではなくhttpに変換されています。信用できるプロキシを自分で追記してやる必要があるみたいですね。
ロードバランサが関係していそうです(定かではありません)。herokuアプリへのリクエストをロードバランスしながら降りけるとかなんとか...
そもそもSSL証明をheroku上ではなく、ドメイン取得時にSSL証明書を取得していれば上記コードの変更は不要だったということも考えられます。
ちなみに下記はlaravelの公式ドキュメントです。

TLS/SSL証明を行うロードバランサの裏でアプリケーションが実行されている場合、アプリケーションが時々HTTPSリンクを生成しないことに、気づくでしょう。典型的な理由は、トラフィックがロードバランサにより80番ポートへフォワーディングされるため、セキュアなリンクを生成すべきだと判断できないからです。

これを解決するには、Laravelアプリケーションに含まれている、App\Http\Middleware\TrustProxiesミドルウェアを使用します。これでアプリケーションにとって信用できるロードバランサやプロキシを簡単にカスタマイズできます。信用できるプロキシをこのミドルウェアの$proxiesプロパティへ配列としてリストしてください。信用するプロキシの設定に加え、オリジナルリクエストに関する情報を含む、プロキシから送られて来るヘッダも設定できます。

引用: https://readouble.com/laravel/5.5/ja/requests.html#configuring-trusted-proxies

おまけ

①httpsが関係していると気付いたのはherokuの環境変数設定で”developement”を指定してみた際に、問題なく認証されたことがきっかけでした。

コマンド

$ heroku config:set APP_ENV="development"

元に戻す時

$ heroku config:set APP_ENV="production"


②こちらはルーティングの設定ですが、お忘れなく。

web.php

Auth::routes(['verify' => true]);