diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 3b10ce2c..9e9478ba 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -344,20 +344,20 @@ class AuthController extends Controller return redirect('/user'); } - public function verify(Request $request) + public function verify(Request $request, User $user) { if (!option('require_verification')) { throw new PrettyPageException(trans('user.verification.disabled'), 1); } - abort_unless($request->hasValidSignature(false), 403, trans('auth.verify.invalid')); + abort_unless($request->hasValidSignature(false) && hash_equals((string)$request->route('hash'), hash('sha256', $user->email)), 403, trans('auth.verify.invalid')); return view('auth.verify'); } public function handleVerify(Request $request, User $user) { - abort_unless($request->hasValidSignature(false), 403, trans('auth.verify.invalid')); + abort_unless($request->hasValidSignature(false) && hash_equals((string)$request->route('hash'), hash('sha256', $user->email)), 403, trans('auth.verify.invalid')); ['email' => $email] = $request->validate(['email' => 'required|email']); diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index c464f992..de36021d 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -157,7 +157,7 @@ class UserController extends Controller return json(trans('user.verification.verified'), 1); } - $url = URL::signedRoute('auth.verify', ['user' => $user], null, false); + $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => $user, 'hash' => hash('sha256', $user->email)], false); try { Mail::to($user->email)->send(new EmailVerification(url($url))); diff --git a/app/Listeners/SendEmailVerification.php b/app/Listeners/SendEmailVerification.php index 097fd169..d1236ab1 100644 --- a/app/Listeners/SendEmailVerification.php +++ b/app/Listeners/SendEmailVerification.php @@ -4,6 +4,7 @@ namespace App\Listeners; use App\Mail\EmailVerification; use App\Models\User; +use Carbon\Carbon; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\URL; @@ -12,7 +13,7 @@ class SendEmailVerification public function handle(User $user) { if (option('require_verification')) { - $url = URL::signedRoute('auth.verify', ['user' => $user->uid], null, false); + $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => $user, 'hash' => hash('sha256', $user->email)], false); try { Mail::to($user->email)->send(new EmailVerification(url($url))); diff --git a/routes/web.php b/routes/web.php index 06cb4ba9..0f5cdf94 100644 --- a/routes/web.php +++ b/routes/web.php @@ -41,8 +41,8 @@ Route::prefix('auth')->name('auth.')->group(function () { Route::post('bind', 'AuthController@fillEmail')->name('verify'); }); - Route::get('verify/{user}', 'AuthController@verify')->name('verify'); - Route::post('verify/{user}', 'AuthController@handleVerify')->name('handle.verify'); + Route::get('verify/{user}/{hash}', 'AuthController@verify')->name('verify'); + Route::post('verify/{user}/{hash}', 'AuthController@handleVerify')->name('handle.verify'); }); Route::prefix('user') diff --git a/tests/HttpTest/ControllersTest/AuthControllerTest.php b/tests/HttpTest/ControllersTest/AuthControllerTest.php index 8331557f..860dd75c 100644 --- a/tests/HttpTest/ControllersTest/AuthControllerTest.php +++ b/tests/HttpTest/ControllersTest/AuthControllerTest.php @@ -724,7 +724,7 @@ class AuthControllerTest extends TestCase public function testVerify() { - $url = URL::signedRoute('auth.verify', ['user' => 1], null, false); + $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => 1, 'hash' => hash('sha256', 'a@b.c')], false); // should be forbidden if account verification is disabled option(['require_verification' => false]); @@ -732,17 +732,17 @@ class AuthControllerTest extends TestCase option(['require_verification' => true]); // invalid link - $this->get(route('auth.verify', ['user' => 1]))->assertForbidden(); + $this->get(route('auth.verify', ['user' => 1, 'hash' => hash('sha256', 'a@b.c')]))->assertForbidden(); $user = User::factory()->create(['verified' => false]); - $url = URL::signedRoute('auth.verify', ['user' => $user], null, false); + $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => $user, 'hash' => hash('sha256', $user->email)], false); $this->get($url)->assertViewIs('auth.verify'); } public function testHandleVerify() { $user = User::factory()->create(['verified' => false]); - $url = URL::signedRoute('auth.verify', ['user' => $user], null, false); + $url = URL::temporarySignedRoute('auth.verify', Carbon::now()->addHour(), ['user' => $user, 'hash' => hash('sha256', $user->email)], false); // empty email $this->post($url, [], ['Referer' => $url])->assertRedirect($url);