Send a reset code by email instead of a link without adding a new field in the database.

Submitted by gabeta - 3 weeks ago

Send a reinitilisation code (6 digits) by email instead of a pratice link for mobile customers. In this case we are using fortify but working well with the laravel authentication system in general.

<?php

/**
 *  Generate and send code by mail
 **/
$request->validate([Fortify::email() => 'required|email']);

Password::broker(config('fortify.passwords'))
    ->sendResetLink(
        $request->only(Fortify::email()), function ($user, $token) {
            $expire = config('auth.passwords.'.config('fortify.passwords').'.expire');
            $digit = random_int(100000, 999999);
            Cache::put($digit.$user->{Fortify::email()}, $token, ($expire * 60));

            Mail::to($user)->send(new ResetPasswordCode($digit, $expire));
        }
    );


/**
 * Resetting the password from the code received by email.
 **/
$request->validate([
    'code' => 'required|digits:6',
    Fortify::email() => 'required|email',
    'password' => 'required',
]);

$cacheKey = $request->code.$request->{Fortify::email()};

throw_unless(Cache::has($cacheKey), ValidationException::withMessages(['code' => 'Invalid code']));

$token = Cache::get($cacheKey);

$attributes = array_merge($request->only(Fortify::email(), 'password', 'password_confirmation'), ['token' => $token]);

Password::broker(config('fortify.passwords'))
    ->reset(
        $attributes,
        function ($user) use ($request) {
            app(ResetsUserPasswords::class)->reset($user, $request->all());
    
            app(CompletePasswordReset::class)(app(StatefulGuard::class), $user);
        }
    );