jeffgreco13 / filament-breezy

MIT License
738 stars 131 forks source link

Use Breezy for global login/register and 2fa #276

Open Jacotheron opened 11 months ago

Jacotheron commented 11 months ago

I am working in a project where we have the public facing side of the web application, where unauthenticated users as well as authenticated users can interact with the application; and then a couple of panels (some of which are multi-tenancy; and then the Admin panel where only the administrators can get).

In short I would like to use Breezy to provide the authentication part, and once logged in (based on user roles, be able to get where I need to go).

Currently the front-end is making use of Laravel Breeze for the authentication there.

How do I change it so that if the user has 2fa in Breezy, that they are asked when they log in (typically at the Breeze login)?

JaZo commented 11 months ago

I've had the same issue, if I understand you correctly (see https://github.com/jeffgreco13/filament-breezy/issues/151). We've eventually configured a separate guard for Filament to circumvent this issue.

Jacotheron commented 11 months ago

Can you perhaps explain how you implemented that guard.

From what I understand, when they log in from the front, the users will need to login again at the back (using the custom guard)? Is this correct?

I see in the other issue you mentioned, it got tagged as Not Planned after they said "This will be standard functionality in Breezy v2"

JaZo commented 11 months ago

That is correct, our workaround does require the user to login on the front-end and back-end separately.

  1. Add extra guard in config/auth.php, which is the same as your normal guard:

    'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    
    'filament' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    ],
  2. Configure filament-guard like this: https://github.com/jeffgreco13/filament-breezy#update-the-auth-guard.

The response on my issue was indeed that it would be implemented v2, but I don't know if that actually happened because I can't find another (documented) way.

Jacotheron commented 11 months ago

I have now done some tests and found that if you have 2FA enabled/forced on a Panel, and your user has 2FA, it will ask you for the code, when you load a filament panel (so not completely login). Obviously if it is forced and you don't have it enabled yet, it will force you to set it up.

I think this is good enough at this time, though I really would like to allow the standard users (that do not visit the panels), to be able to also enable 2FA for added security (using the same 2fa mechanism as what I will use).

Jacotheron commented 11 months ago

Having looked at the Breezy code, I came up with a way to use it on the frontend as well as the back end (no need to re-login).

Since it is much more than I want to write out in a reply, I made a Gist with the steps. It can be viewed at Using Breezy Filament 2FA with Laravel Breeze (Blade) for all users

A short summary:

  1. Created a Profile section, using Livewire, which mimics the Breezy section to enable/disable the 2FA. This part uses Filament Forms and Actions on the frontend, so be sure to set it up based on the docs (in the Gist I have summarized the steps to do this). Add the new section to the 'profile.edit' blade view.
  2. I then created 2 new methods on the "AuthenticatedSessionController.php" which Laravel Breeze use to handle the Login, to handle the display and verification of the 2FA. Along with the blade view for the form. The form supports the code or a recovery code (when checking the checkbox for the recovery code).
  3. The validate method, makes use of a FormRequest, which also handles the verification of the code (the base of the form request is the Login form request, but adapted to verify the code the same way Breezy does it - though simplified).
  4. Finally we have a Middleware which detects if the current user has 2fa, and a valid 2fa session. Only if the user is logged in, has 2fa and does not have a valid 2fa session, will it redirect the user to the 2fa code page. I have added this to my 'web' middleware group, and everything seems to work fine.

I have performed some tests, though will continue with the tests over the next few days, and so far it works great.

I can enable/disable 2fa on the frontend and filament backend; and then use either login form to log in, provide the code or recovery code and access both the frontend and backend with no issues.

I have also now disabled the Filament panel's login, and now it simply redirects to the Breeze Login form, simplifying everything.

The middleware has a place where routes can be ignored for the Intended Redirect section, as I found the Livewire requests caused an issue with this redirect.

I hope this can help someone else as well, and if someone is willing to build a plugin from this, go for it.

JaZo commented 11 months ago

Great find and nice write up!