Browse Source

Updated hashing algo for verify email URL

Will Browning 3 years ago
parent
commit
dd0ea08402

+ 2 - 1
app/Http/Controllers/Auth/VerificationController.php

@@ -9,6 +9,7 @@ use Illuminate\Auth\Access\AuthorizationException;
 use Illuminate\Auth\Events\Verified;
 use Illuminate\Foundation\Auth\VerifiesEmails;
 use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Hash;
 
 class VerificationController extends Controller
 {
@@ -64,7 +65,7 @@ class VerificationController extends Controller
             throw new AuthorizationException;
         }
 
-        if (! hash_equals((string) $request->route('hash'), sha1($verifiable->getEmailForVerification()))) {
+        if (! Hash::check($verifiable->getEmailForVerification(), (string) base64_decode($request->route('hash')))) {
             throw new AuthorizationException;
         }
 

+ 2 - 2
app/Models/Recipient.php

@@ -2,10 +2,10 @@
 
 namespace App\Models;
 
+use App\Notifications\CustomVerifyEmail;
 use App\Notifications\UsernameReminder;
 use App\Traits\HasEncryptedAttributes;
 use App\Traits\HasUuid;
-use Illuminate\Auth\Notifications\VerifyEmail;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 
@@ -138,7 +138,7 @@ class Recipient extends Model
      */
     public function sendEmailVerificationNotification()
     {
-        $this->notify(new VerifyEmail);
+        $this->notify(new CustomVerifyEmail);
     }
 
     /**

+ 11 - 0
app/Models/User.php

@@ -2,6 +2,7 @@
 
 namespace App\Models;
 
+use App\Notifications\CustomVerifyEmail;
 use App\Traits\HasEncryptedAttributes;
 use App\Traits\HasUuid;
 use Illuminate\Contracts\Auth\MustVerifyEmail;
@@ -266,6 +267,16 @@ class User extends Authenticatable implements MustVerifyEmail
         $this->update(['catch_all' => true]);
     }
 
+    /**
+     * Send the email verification notification.
+     *
+     * @return void
+     */
+    public function sendEmailVerificationNotification()
+    {
+        $this->notify(new CustomVerifyEmail);
+    }
+
     public function hasVerifiedDefaultRecipient()
     {
         return ! is_null($this->defaultRecipient->email_verified_at);

+ 71 - 0
app/Notifications/CustomVerifyEmail.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace App\Notifications;
+
+use App\Models\User;
+use Illuminate\Auth\Notifications\VerifyEmail;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldBeEncrypted;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Notifications\Messages\MailMessage;
+use Illuminate\Support\Carbon;
+use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\Hash;
+use Illuminate\Support\Facades\Lang;
+use Illuminate\Support\Facades\URL;
+
+class CustomVerifyEmail extends VerifyEmail implements ShouldQueue, ShouldBeEncrypted
+{
+    use Queueable;
+
+    /**
+     * Build the mail representation of the notification.
+     *
+     * @param  mixed  $notifiable
+     * @return \Illuminate\Notifications\Messages\MailMessage
+     */
+    public function toMail($notifiable)
+    {
+        $verificationUrl = $this->verificationUrl($notifiable);
+
+        if (static::$toMailCallback) {
+            return call_user_func(static::$toMailCallback, $notifiable, $verificationUrl);
+        }
+
+        $feedbackId = $notifiable instanceof User ? 'VU:anonaddy' : 'VR:anonaddy';
+        $recipientId = $notifiable instanceof User ? $notifiable->default_recipient_id : $notifiable->id;
+
+        return (new MailMessage)
+            ->subject(Lang::get('Verify Email Address'))
+            ->markdown('mail.verify_email', [
+                'verificationUrl' => $verificationUrl,
+                'recipientId' => $recipientId
+            ])
+            ->withSwiftMessage(function ($message) use ($feedbackId) {
+                $message->getHeaders()
+                        ->addTextHeader('Feedback-ID', $feedbackId);
+            });
+    }
+
+    /**
+     * Get the verification URL for the given notifiable.
+     *
+     * @param  mixed  $notifiable
+     * @return string
+     */
+    protected function verificationUrl($notifiable)
+    {
+        if (static::$createUrlCallback) {
+            return call_user_func(static::$createUrlCallback, $notifiable);
+        }
+
+        return URL::temporarySignedRoute(
+            'verification.verify',
+            Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
+            [
+                'id' => $notifiable->getKey(),
+                'hash' => base64_encode(Hash::make($notifiable->getEmailForVerification())),
+            ]
+        );
+    }
+}

+ 53 - 18
composer.lock

@@ -1849,16 +1849,16 @@
         },
         {
             "name": "guzzlehttp/psr7",
-            "version": "1.8.2",
+            "version": "1.8.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/guzzle/psr7.git",
-                "reference": "dc960a912984efb74d0a90222870c72c87f10c91"
+                "reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
-                "reference": "dc960a912984efb74d0a90222870c72c87f10c91",
+                "url": "https://api.github.com/repos/guzzle/psr7/zipball/1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
+                "reference": "1afdd860a2566ed3c2b0b4a3de6e23434a79ec85",
                 "shasum": ""
             },
             "require": {
@@ -1895,13 +1895,34 @@
                 "MIT"
             ],
             "authors": [
+                {
+                    "name": "Graham Campbell",
+                    "email": "hello@gjcampbell.co.uk",
+                    "homepage": "https://github.com/GrahamCampbell"
+                },
                 {
                     "name": "Michael Dowling",
                     "email": "mtdowling@gmail.com",
                     "homepage": "https://github.com/mtdowling"
                 },
+                {
+                    "name": "George Mponos",
+                    "email": "gmponos@gmail.com",
+                    "homepage": "https://github.com/gmponos"
+                },
+                {
+                    "name": "Tobias Nyholm",
+                    "email": "tobias.nyholm@gmail.com",
+                    "homepage": "https://github.com/Nyholm"
+                },
+                {
+                    "name": "Márk Sági-Kazár",
+                    "email": "mark.sagikazar@gmail.com",
+                    "homepage": "https://github.com/sagikazarmark"
+                },
                 {
                     "name": "Tobias Schultze",
+                    "email": "webmaster@tubo-world.de",
                     "homepage": "https://github.com/Tobion"
                 }
             ],
@@ -1918,9 +1939,23 @@
             ],
             "support": {
                 "issues": "https://github.com/guzzle/psr7/issues",
-                "source": "https://github.com/guzzle/psr7/tree/1.8.2"
+                "source": "https://github.com/guzzle/psr7/tree/1.8.3"
             },
-            "time": "2021-04-26T09:17:50+00:00"
+            "funding": [
+                {
+                    "url": "https://github.com/GrahamCampbell",
+                    "type": "github"
+                },
+                {
+                    "url": "https://github.com/Nyholm",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/guzzlehttp/psr7",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2021-10-05T13:56:00+00:00"
         },
         {
             "name": "intervention/image",
@@ -2008,16 +2043,16 @@
         },
         {
             "name": "laravel/framework",
-            "version": "v8.62.0",
+            "version": "v8.63.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/laravel/framework.git",
-                "reference": "60a7e00488167ce2babf3a2aeb3677e48aaf39be"
+                "reference": "8f3d280f36a427730c8c8fa34316c79eed38781e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/laravel/framework/zipball/60a7e00488167ce2babf3a2aeb3677e48aaf39be",
-                "reference": "60a7e00488167ce2babf3a2aeb3677e48aaf39be",
+                "url": "https://api.github.com/repos/laravel/framework/zipball/8f3d280f36a427730c8c8fa34316c79eed38781e",
+                "reference": "8f3d280f36a427730c8c8fa34316c79eed38781e",
                 "shasum": ""
             },
             "require": {
@@ -2175,7 +2210,7 @@
                 "issues": "https://github.com/laravel/framework/issues",
                 "source": "https://github.com/laravel/framework"
             },
-            "time": "2021-09-28T13:30:25+00:00"
+            "time": "2021-10-05T14:04:25+00:00"
         },
         {
             "name": "laravel/passport",
@@ -10075,16 +10110,16 @@
         },
         {
             "name": "friendsofphp/php-cs-fixer",
-            "version": "v3.2.0",
+            "version": "v3.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git",
-                "reference": "29f37e3356286297c025e6e71778e6da78f808e9"
+                "reference": "13ae36a76b6e329e44ca3cafaa784ea02db9ff14"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/29f37e3356286297c025e6e71778e6da78f808e9",
-                "reference": "29f37e3356286297c025e6e71778e6da78f808e9",
+                "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/13ae36a76b6e329e44ca3cafaa784ea02db9ff14",
+                "reference": "13ae36a76b6e329e44ca3cafaa784ea02db9ff14",
                 "shasum": ""
             },
             "require": {
@@ -10093,7 +10128,7 @@
                 "doctrine/annotations": "^1.12",
                 "ext-json": "*",
                 "ext-tokenizer": "*",
-                "php": "^7.1.3 || ^8.0",
+                "php": "^7.2 || ^8.0",
                 "php-cs-fixer/diff": "^2.0",
                 "symfony/console": "^4.4.20 || ^5.1.3",
                 "symfony/event-dispatcher": "^4.4.20 || ^5.0",
@@ -10153,7 +10188,7 @@
             "description": "A tool to automatically fix PHP code style",
             "support": {
                 "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues",
-                "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.2.0"
+                "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v3.2.1"
             },
             "funding": [
                 {
@@ -10161,7 +10196,7 @@
                     "type": "github"
                 }
             ],
-            "time": "2021-10-05T07:28:14+00:00"
+            "time": "2021-10-05T08:12:17+00:00"
         },
         {
             "name": "hamcrest/hamcrest-php",

+ 2 - 2
config/version.yml

@@ -5,9 +5,9 @@ current:
   major: 0
   minor: 8
   patch: 4
-  prerelease: ''
+  prerelease: 1-g0478d9e
   buildmetadata: ''
-  commit: 14de41
+  commit: 0478d9
   timestamp:
     year: 2020
     month: 10

+ 44 - 44
package-lock.json

@@ -1776,9 +1776,9 @@
             "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
         },
         "node_modules/@types/node": {
-            "version": "16.10.2",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.2.tgz",
-            "integrity": "sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ=="
+            "version": "16.10.3",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.3.tgz",
+            "integrity": "sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ=="
         },
         "node_modules/@types/parse-json": {
             "version": "4.0.0",
@@ -2755,9 +2755,9 @@
             }
         },
         "node_modules/caniuse-lite": {
-            "version": "1.0.30001264",
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001264.tgz",
-            "integrity": "sha512-Ftfqqfcs/ePiUmyaySsQ4PUsdcYyXG2rfoBVsk3iY1ahHaJEw65vfb7Suzqm+cEkwwPIv/XWkg27iCpRavH4zA==",
+            "version": "1.0.30001265",
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz",
+            "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==",
             "funding": {
                 "type": "opencollective",
                 "url": "https://opencollective.com/browserslist"
@@ -3140,11 +3140,11 @@
             "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
         },
         "node_modules/core-js-compat": {
-            "version": "3.18.1",
-            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.18.1.tgz",
-            "integrity": "sha512-XJMYx58zo4W0kLPmIingVZA10+7TuKrMLPt83+EzDmxFJQUMcTVVmQ+n5JP4r6Z14qSzhQBRi3NSWoeVyKKXUg==",
+            "version": "3.18.2",
+            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.18.2.tgz",
+            "integrity": "sha512-25VJYCJtGjZwLguj7d66oiHfmnVw3TMOZ0zV8DyMJp/aeQ3OjR519iOOeck08HMyVVRAqXxafc2Hl+5QstJrsQ==",
             "dependencies": {
-                "browserslist": "^4.17.1",
+                "browserslist": "^4.17.3",
                 "semver": "7.0.0"
             },
             "funding": {
@@ -3489,9 +3489,9 @@
             }
         },
         "node_modules/date-fns": {
-            "version": "2.24.0",
-            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.24.0.tgz",
-            "integrity": "sha512-6ujwvwgPID6zbI0o7UbURi2vlLDR9uP26+tW6Lg+Ji3w7dd0i3DOcjcClLjLPranT60SSEFBwdSyYwn/ZkPIuw==",
+            "version": "2.25.0",
+            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
+            "integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w==",
             "engines": {
                 "node": ">=0.11"
             },
@@ -3834,9 +3834,9 @@
             "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
         },
         "node_modules/electron-to-chromium": {
-            "version": "1.3.859",
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.859.tgz",
-            "integrity": "sha512-gXRXKNWedfdiKIzwr0Mg/VGCvxXzy+4SuK9hp1BDvfbCwx0O5Ot+2f4CoqQkqEJ3Zj/eAV/GoAFgBVFgkBLXuQ=="
+            "version": "1.3.860",
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.860.tgz",
+            "integrity": "sha512-gWwGZ+Wv4Mou2SJRH6JQzhTPjL5f95SX7n6VkLTQ/Q/INsZLZNQ1vH2GlZjozKyvT0kkFuCmWTwIoCj+/hUDPw=="
         },
         "node_modules/elliptic": {
             "version": "6.5.4",
@@ -5994,9 +5994,9 @@
             "integrity": "sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ=="
         },
         "node_modules/nanoid": {
-            "version": "3.1.28",
-            "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.28.tgz",
-            "integrity": "sha512-gSu9VZ2HtmoKYe/lmyPFES5nknFrHa+/DT9muUFWFMi6Jh9E1I7bkvlQ8xxf1Kos9pi9o8lBnIOkatMhKX/YUw==",
+            "version": "3.1.29",
+            "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.29.tgz",
+            "integrity": "sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg==",
             "bin": {
                 "nanoid": "bin/nanoid.cjs"
             },
@@ -8876,9 +8876,9 @@
             }
         },
         "node_modules/webpack": {
-            "version": "5.56.1",
-            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.56.1.tgz",
-            "integrity": "sha512-MRbTPooHJuSAfbx7Lh/qEMRUe/d0p4cRj2GPo/fq+4JUeR/+Q1EfLvS1lexslbMcJZyPXxxz/k/NzVepkA5upA==",
+            "version": "5.57.1",
+            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.57.1.tgz",
+            "integrity": "sha512-kHszukYjTPVfCOEyrUthA3jqJwduY/P3eO8I0gMNOZGIQWKAwZftxmp5hq6paophvwo9NoUrcZOecs9ulOyyTg==",
             "dependencies": {
                 "@types/eslint-scope": "^3.7.0",
                 "@types/estree": "^0.0.50",
@@ -10540,9 +10540,9 @@
             "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ=="
         },
         "@types/node": {
-            "version": "16.10.2",
-            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.2.tgz",
-            "integrity": "sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ=="
+            "version": "16.10.3",
+            "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.3.tgz",
+            "integrity": "sha512-ho3Ruq+fFnBrZhUYI46n/bV2GjwzSkwuT4dTf0GkuNFmnb8nq4ny2z9JEVemFi6bdEJanHLlYfy9c6FN9B9McQ=="
         },
         "@types/parse-json": {
             "version": "4.0.0",
@@ -11335,9 +11335,9 @@
             }
         },
         "caniuse-lite": {
-            "version": "1.0.30001264",
-            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001264.tgz",
-            "integrity": "sha512-Ftfqqfcs/ePiUmyaySsQ4PUsdcYyXG2rfoBVsk3iY1ahHaJEw65vfb7Suzqm+cEkwwPIv/XWkg27iCpRavH4zA=="
+            "version": "1.0.30001265",
+            "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz",
+            "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw=="
         },
         "chalk": {
             "version": "4.1.2",
@@ -11640,11 +11640,11 @@
             "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
         },
         "core-js-compat": {
-            "version": "3.18.1",
-            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.18.1.tgz",
-            "integrity": "sha512-XJMYx58zo4W0kLPmIingVZA10+7TuKrMLPt83+EzDmxFJQUMcTVVmQ+n5JP4r6Z14qSzhQBRi3NSWoeVyKKXUg==",
+            "version": "3.18.2",
+            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.18.2.tgz",
+            "integrity": "sha512-25VJYCJtGjZwLguj7d66oiHfmnVw3TMOZ0zV8DyMJp/aeQ3OjR519iOOeck08HMyVVRAqXxafc2Hl+5QstJrsQ==",
             "requires": {
-                "browserslist": "^4.17.1",
+                "browserslist": "^4.17.3",
                 "semver": "7.0.0"
             },
             "dependencies": {
@@ -11899,9 +11899,9 @@
             }
         },
         "date-fns": {
-            "version": "2.24.0",
-            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.24.0.tgz",
-            "integrity": "sha512-6ujwvwgPID6zbI0o7UbURi2vlLDR9uP26+tW6Lg+Ji3w7dd0i3DOcjcClLjLPranT60SSEFBwdSyYwn/ZkPIuw=="
+            "version": "2.25.0",
+            "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.25.0.tgz",
+            "integrity": "sha512-ovYRFnTrbGPD4nqaEqescPEv1mNwvt+UTqI3Ay9SzNtey9NZnYu6E2qCcBBgJ6/2VF1zGGygpyTDITqpQQ5e+w=="
         },
         "dayjs": {
             "version": "1.10.7",
@@ -12164,9 +12164,9 @@
             "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
         },
         "electron-to-chromium": {
-            "version": "1.3.859",
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.859.tgz",
-            "integrity": "sha512-gXRXKNWedfdiKIzwr0Mg/VGCvxXzy+4SuK9hp1BDvfbCwx0O5Ot+2f4CoqQkqEJ3Zj/eAV/GoAFgBVFgkBLXuQ=="
+            "version": "1.3.860",
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.860.tgz",
+            "integrity": "sha512-gWwGZ+Wv4Mou2SJRH6JQzhTPjL5f95SX7n6VkLTQ/Q/INsZLZNQ1vH2GlZjozKyvT0kkFuCmWTwIoCj+/hUDPw=="
         },
         "elliptic": {
             "version": "6.5.4",
@@ -13768,9 +13768,9 @@
             "integrity": "sha512-2nMHqg1x5PU+unxX7PGY7AuYxl2qDx7PSrTRjizr8sxdd3l/3hBuWWaki62qmtYm2U5i4Z5E7GbjlyDFhs9/EQ=="
         },
         "nanoid": {
-            "version": "3.1.28",
-            "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.28.tgz",
-            "integrity": "sha512-gSu9VZ2HtmoKYe/lmyPFES5nknFrHa+/DT9muUFWFMi6Jh9E1I7bkvlQ8xxf1Kos9pi9o8lBnIOkatMhKX/YUw=="
+            "version": "3.1.29",
+            "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.29.tgz",
+            "integrity": "sha512-dW2pUSGZ8ZnCFIlBIA31SV8huOGCHb6OwzVCc7A69rb/a+SgPBwfmLvK5TKQ3INPbRkcI8a/Owo0XbiTNH19wg=="
         },
         "negotiator": {
             "version": "0.6.2",
@@ -15882,9 +15882,9 @@
             }
         },
         "webpack": {
-            "version": "5.56.1",
-            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.56.1.tgz",
-            "integrity": "sha512-MRbTPooHJuSAfbx7Lh/qEMRUe/d0p4cRj2GPo/fq+4JUeR/+Q1EfLvS1lexslbMcJZyPXxxz/k/NzVepkA5upA==",
+            "version": "5.57.1",
+            "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.57.1.tgz",
+            "integrity": "sha512-kHszukYjTPVfCOEyrUthA3jqJwduY/P3eO8I0gMNOZGIQWKAwZftxmp5hq6paophvwo9NoUrcZOecs9ulOyyTg==",
             "requires": {
                 "@types/eslint-scope": "^3.7.0",
                 "@types/estree": "^0.0.50",

+ 18 - 0
resources/views/mail/verify_email.blade.php

@@ -0,0 +1,18 @@
+@component('mail::message')
+
+# Hello!
+
+Please click the button below to verify your email address.
+
+@component('mail::button', ['url' => $verificationUrl])
+Verify Email Address
+@endcomponent
+
+If you did not create an account, no further action is required.
+
+@component('mail::subcopy')
+If you’re having trouble clicking the "Verify Email Address" button, copy and paste the URL below
+into your web browser: <span class="break-all">[{{ $verificationUrl }}]({{ $verificationUrl }})</span>
+@endcomponent
+
+@endcomponent

+ 4 - 3
tests/Feature/RegistrationTest.php

@@ -6,10 +6,11 @@ use App\Models\AdditionalUsername;
 use App\Models\DeletedUsername;
 use App\Models\Recipient;
 use App\Models\User;
-use Illuminate\Auth\Notifications\VerifyEmail;
+use App\Notifications\CustomVerifyEmail;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 use Illuminate\Support\Carbon;
 use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Facades\Notification;
 use Illuminate\Support\Facades\URL;
 use Tests\TestCase;
@@ -43,7 +44,7 @@ class RegistrationTest extends TestCase
 
         Notification::assertSentTo(
             $user,
-            VerifyEmail::class
+            CustomVerifyEmail::class
         );
     }
 
@@ -79,7 +80,7 @@ class RegistrationTest extends TestCase
             Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
             [
                 'id' => $user->getKey(),
-                'hash' => sha1($user->getEmailForVerification()),
+                'hash' => base64_encode(Hash::make($user->getEmailForVerification())),
             ]
         );
 

+ 5 - 4
tests/Feature/ShowRecipientsTest.php

@@ -6,10 +6,11 @@ use App\Models\Alias;
 use App\Models\AliasRecipient;
 use App\Models\Recipient;
 use App\Models\User;
-use Illuminate\Auth\Notifications\VerifyEmail;
+use App\Notifications\CustomVerifyEmail;
 use Illuminate\Foundation\Testing\RefreshDatabase;
 use Illuminate\Support\Carbon;
 use Illuminate\Support\Facades\Config;
+use Illuminate\Support\Facades\Hash;
 use Illuminate\Support\Facades\Notification;
 use Illuminate\Support\Facades\URL;
 use Tests\TestCase;
@@ -110,7 +111,7 @@ class ShowRecipientsTest extends TestCase
 
         Notification::assertSentTo(
             $recipient,
-            VerifyEmail::class
+            CustomVerifyEmail::class
         );
     }
 
@@ -129,7 +130,7 @@ class ShowRecipientsTest extends TestCase
             Carbon::now()->addMinutes(Config::get('auth.verification.expire', 60)),
             [
                 'id' => $recipient->getKey(),
-                'hash' => sha1($recipient->getEmailForVerification()),
+                'hash' => base64_encode(Hash::make($recipient->getEmailForVerification())),
             ]
         );
 
@@ -162,7 +163,7 @@ class ShowRecipientsTest extends TestCase
 
         Notification::assertSentTo(
             $recipient,
-            VerifyEmail::class
+            CustomVerifyEmail::class
         );
 
         $response2 = $this->json('POST', '/recipients/email/resend', [