Laravel password reset functionality not working correctly

I need help with my Laravel password reset system. The code runs without errors but there’s a weird bug. When someone gets a password reset email and changes their password, it doesn’t update the correct user. Instead, it always changes the password for the first user in the database table. I can’t figure out why this is happening.

Routes (api.php):

Route::post('/forgot-password', [AuthController::class, 'sendResetLink']);

Routes (web.php):

Route::get('/change-password', [AuthController::class, 'showResetForm']);
Route::post('/change-password', [AuthController::class, 'updatePassword']);

Controller:

class AuthController extends Controller
{
    public function sendResetLink(Request $request)
    {
        $userRecord = User::where('email', $request->email)->first();
        
        if ($userRecord) {
            $resetToken = Str::random(50);
            $baseUrl = URL::to('/');
            $resetUrl = $baseUrl + '/change-password?token=' + $resetToken;
            
            $emailData = [
                'link' => $resetUrl,
                'user_email' => $request->email,
                'subject' => 'Reset Your Password'
            ];
            
            Mail::send('emails.password-reset', $emailData, function($msg) use ($emailData) {
                $msg->to($emailData['user_email'])->subject($emailData['subject']);
            });
            
            TokenReset::updateOrCreate(
                ['email' => $request->email],
                ['token' => $resetToken, 'created_at' => now()]
            );
            
            return response()->json(['status' => 'success']);
        }
        
        return response()->json(['status' => 'error', 'msg' => 'User not found']);
    }
    
    public function updatePassword(Request $request)
    {
        $request->validate(['password' => 'required|min:8|confirmed']);
        
        $userAccount = User::find($request->user_id);
        $userAccount->password = Hash::make($request->password);
        $userAccount->save();
        
        return '<h2>Password updated successfully!</h2>';
    }
}

Reset Form (change-password.blade.php):

<form method="POST">
    @csrf
    <input type="hidden" name="user_id" value="{{$userAccount[0]['id']}}">
    <label>New Password:</label>
    <input type="password" name="password" required>
    <label>Confirm Password:</label>
    <input type="password" name="password_confirmation" required>
    <button type="submit">Update Password</button>
</form>

Any ideas what might be causing this issue? Thanks for any help!

The issue is your missing showResetForm method that everyone’s mentioned. You’re passing $userAccount[0]['id'] to the form, which means you’re getting an array instead of a single user object - probably just grabbing the first user by default. Your form submission jumps straight to updatePassword without checking the token. You need showResetForm to grab the token from the URL, look it up in your TokenReset table, find the email, then get that specific user for the view. Also, fix that string concatenation in your reset URL - PHP uses dots, not plus signs.

I hit this same issue recently. Your showResetForm method needs to grab the right user based on the token, not just default to the first one. That $userAccount[0]['id'] line shows you’re treating the result like an array when you should be getting a single user object. Make sure you’re validating the token against the correct user in your TokenReset table before updating the password. Also, quick PHP tip - use . for string concatenation in your $resetUrl, not +. Fix these and your updates should work.

the problem’s in your showResetForm method - you’re not validating the token properly and just returning the first user every time. also, that $userAccount[0]['id'] in your blade looks wrong - it shouldn’t be an array. fix your showResetForm to actually match the token with the right user email first.