Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use Laravel Livewire with Laravel Fortify for Login

I'm wanting to use Laravel Fortify and Livewire to create a very simple login form. I do not want to use Jetstream as it has more features that I do not need vs features I do need.

I'm using livewire throughout my app, and would like to use it for my login page to provide real time instant validation.

The problem I am encountering is I am unable to submit the form with values if I'm using wire:model on inputs.

I also can not use auth()->attempt() because it is being hijacked by Fortify.(At least, I think it is. All know is when I use it, it returns false)

How can I use livewire with fortify? I need to send the data from the livewire component to POST /login.

Here is my current set up:

FortifyServiceProvider.php

public function boot()
    {
        Fortify::createUsersUsing(CreateNewUser::class);
        Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
        Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
        Fortify::resetUserPasswordsUsing(ResetUserPassword::class);

        // Custom Fortify Views =============================

        // Login Page
        Fortify::loginView(function () {
            return view('auth.login');
        });
   }

My auth/login.blade.php (simply calls the livewire components with the proper layout template)

<x-layouts.auth>
    @livewire('auth.login')
</x-layouts.auth>

The livewire component livewire/auth/login.blade.php:

<form wire:submit.prevent="login" action="#" method="POST">
    <div>
        <label for="email">Email address</label>
        <input wire:model="email" id="email" type="email" required autofocus>
        @error('email'){{ $message }}@enderror
    </div>

    <div>
        <label for="password">Password</label>
        <input wire:model.lazy="password" id="password" type="password" required>
        @error('password'){{ $message }}@enderror
    </div>

    <div>
        <input wire:model.lazy="remember" id="remember_me" type="checkbox">
        <label for="remember_me">Remember me</label>

        <a href="#">Forgot your password?</a>
    </div>

    <div>
        <button type="submit">Sign in</button>
    </div>
</form>

and my Http/Livewire/Auth/Login.php file for the livewire component:

class Login extends Component
{
    public $email = '';
    public $password = '';
    public $remember = false;

    protected $rules = [
        'email' => 'required|email|exists:users,email',
        'password' => 'required',
    ];

    /**
     * Shows Real time validation for email field
     */
    public function updatedEmail() {
        $this->validate(['email' => 'email|exists:users,email']);
    }

    /**
     * Logs user in when form is submitted
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Support\MessageBag
     */
    public function login()
    {
        // ******* Need to submit the form to Fortify here?? ******
    }

    /**
     * Renders the view
     * @return mixed
     */
    public function render()
    {
        return view('livewire.auth.login')
            ->layout('layouts.auth');
    }
}
like image 220
xslibx Avatar asked Nov 30 '25 08:11

xslibx


2 Answers

class Login extends Component
{
  public $email = '';
  public $password = '';
......

First of all, accoring to the Livewire documentation, sensitive information(such as passwords) SHOULD NOT BE used as public properties in livewire components. Therefore you should think twice before using livewire with user authentication.

protected $rules = [
  'email' => 'required|email|exists:users,email',
  'password' => 'required',
];

Next, in validation rules you are using exists:user,email which would validate real-time if an email is in the database. I would advice against using this validation with livewire real-time validation rule in production systems as it could be easily used by a malicious actor to extract email list of users of your system.

That being said, there are ways for you to authenticate(but not using Fortify) inside you login function. for example:

class LoginForm extends Component
{
public $email = '';
public $password = '';
public $remember = false;

protected $rules = [
    'email' => 'required|email|exists:users,email',
    'password' => 'required',
];

/*

Sometimes it's useful to validate a form field as a user types into it. 
Livewire makes "real-time" validation simple with the $this->validateOnly() method.

To validate an input field after every update, we can use Livewire's updated hook:

 */
public function updated($propertyName)
{
    $this->validateOnly($propertyName);
}

public function render()
{
    return view('livewire.loginForm');
}

public function login()
{
    $this->validate();

    // Execution doesn't reach here if validation fails.

    $email = $this->email;
    $password = $this->password;
    $credentials = ['email'=>$email, 'password'=>$password];

    if (Auth::attempt($credentials)) {
        // Auth success
    }

    else{
        // Auth failed
    }
}

}

Then again, when using this method, you are only using Fortify to retrieve the login page which is definitely not the intended use of Fortify. Therefore after considering all the issues, I think it is best you avoid using livewire for user authentication process.

like image 138
uj95 Avatar answered Dec 02 '25 05:12

uj95


I tried to install a new project with only Livewire and Fortify to simulate your scenario. After a long pondering, these are my findings

  1. It's the most confusing part when I saw the login() method and started to think that this method will handle the authentication or forward it or something.
  2. Fortify uses its own routs, so you can't do the authentication without sending your form data to the "/login" endpoint.
  3. Your livewire component will help with showing the real-time validation errors, (maybe you can disable the form submit button until the validation passes).
  4. Let Fortify handle the authentication for you and set your form to submit

<form method="POST" action="{{ route('login') }}">

  1. If you need to customize the authentication process, Fortify offers you this feature easily, see the documentation
  2. If you insist to use the login() method I think you can create a PHP POST request to send the fields, but I can't see the point in doing that.

I hope this will give you the idea.

like image 40
Ali Ali Avatar answered Dec 02 '25 04:12

Ali Ali



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!