query('redirect', ''); if (preg_match('#^/(?![/\\\\])#', $redirect)) { $request->session()->put('url.intended', url($redirect)); } return view('auth.login'); } public function send(string $locale, Request $request, UserOtpService $otp): RedirectResponse { // Captcha only here: verify() and resend() need the email this step // puts in the session, so they can't be reached without passing it. $validated = $request->validate([ 'email' => ['required', 'email', 'max:255'], 'h-captcha-response' => ['bail', 'required', new HCaptcha], ], [ 'h-captcha-response.required' => __('storefront.auth.captcha_failed'), ]); $email = Str::lower(trim($validated['email'])); try { $otp->generateAndSend($email); } catch (OtpThrottledException) { return back()->withInput()->withErrors([ 'email' => __('storefront.auth.too_many_codes'), ]); } $request->session()->put('login.email', $email); return redirect()->route('login.code'); } public function code(string $locale, Request $request): View|RedirectResponse { $email = $request->session()->get('login.email'); if (! $email) { return redirect()->route('login'); } return view('auth.login-code', ['email' => $email]); } public function resend(string $locale, Request $request, UserOtpService $otp): RedirectResponse { $email = $request->session()->get('login.email'); if (! $email) { return redirect()->route('login'); } try { $otp->generateAndSend($email); } catch (OtpThrottledException) { return back()->withErrors([ 'code' => __('storefront.auth.too_many_codes'), ]); } return back()->with('status', __('storefront.auth.code_resent')); } public function verify(string $locale, Request $request, UserOtpService $otp): RedirectResponse { $email = $request->session()->get('login.email'); if (! $email) { return redirect()->route('login'); } $validated = $request->validate([ 'code' => ['required', 'digits:6'], ]); // Wrong, expired, or locked out after too many guesses — core doesn't // say which, so neither do we; the page offers "resend code" for all three. if (! $otp->validate($email, $validated['code'], $request)) { return back()->withErrors([ 'code' => __('storefront.auth.invalid_code'), ]); } $request->session()->forget('login.email'); return redirect()->intended(route('home')); } public function destroy(string $locale, Request $request): RedirectResponse { Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect()->route('home'); } }