メールアドレスの認証をするのにバックエンドのLaravelへクライアント側から直接GETアクセスが飛ぶけどまあいっかと思っていたのですが、気になるのでやっぱりメールアドレス認証のメールのURLをカスタマイズします。
メールアドレス認証処理のカスタマイズ
メール認証用URLの変更
app\Providers\AuthServiceProvider.phpのbootメソッド内でVerifyEmail::createUrlUsingメソッドを使い、メール認証で生成されるURLをカスタマイズします。
41行目:.envファイルからベースとなるURLを取得します。
43-50行目:Sanctumのverification.verifyルートへ60分間有効なルートを生成してします。
52-53行目:生成したURLから必要な値を抽出しています。
55行目:クライアント側で使いやすいようにURLとパラメータを整形しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
<?php namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Gate; use Illuminate\Auth\Notifications\ResetPassword; use Illuminate\Auth\Notifications\VerifyEmail; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\URL; use Illuminate\Support\Facades\Config; class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ // 'App\Models\Model' => 'App\Policies\ModelPolicy', ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); ResetPassword::createUrlUsing(function ($user, string $token) { return env('HOME_URL') . '/reset-password?email=' . $user->email . '&token=' . $token; }); // VerifyEmail::createUrlUsing(function ($notifiable) { $frontendUrl = env('HOME_URL'); $verifyUrl = URL::temporarySignedRoute( 'verification.verify', Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)), [ 'id' => $notifiable->getKey(), 'hash' => sha1($notifiable->getEmailForVerification()), ] ); $parsed_url = parse_url($verifyUrl); $exploded = explode('/', $parsed_url['path']); return $frontendUrl . '/verification?id=' . $notifiable->getKey() . '&hash=' . end($exploded) . '&' . $parsed_url['query']; }); } } |
上記のコードは大半がvendor\laravel\framework\src\Illuminate\Auth\Notifications\VerifyEmail.phpのverificationUrlメソッドのままです。
認証用ページの作成
先ほど/verificationを認証用のページとして指定したので、pages\verification.vueファイルを作り、以下の様に編集します。特にコンテンツは無しで、Fortifyが用意しているemail/verifyへGETリクエストを投げるだけです。正常ならユーザー情報をフェッチし、ルートへ移動させています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<template></template> <script> export default { async created() { try { console.dir(this.$route.query); await this.$axios.get("email/verify/" + this.$route.query.id + "/" + this.$route.query.hash + "?expires=" + this.$route.query.expires + "&signature=" + this.$route.query.signature); await this.$auth.fetchUser(); this.$router.replace("/"); } catch (e) {} }, }; </script> |
cors対策
config\cors.phpのpathsに'email/verify/*'を追加します。
ページプロテクトの解除
middleware\verified.jsで/verificationページもスルーする用に修正します。2行目でverificationも除外しています。
1 2 3 4 5 6 7 8 9 |
export default function ({ route, $auth, redirect }) { if (route.fullPath !== "/verify" && route.path !== "/verification") { if ($auth.user) { if (!$auth.user.email_verified_at) { return redirect("verify"); } } } } |
実行
これで実装できましたので実行してみます。以下の様な動作になります。
最後に
あまり気にすることもない気もしますが一応認証もSPAで実施できるようになりました。