laravel / fortify

Backend controllers and scaffolding for Laravel authentication.

Home Page:https://laravel.com/docs/fortify

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Not triggering 2FA challenge in existing app?

frequentredundancy opened this issue · comments

  • Fortify Version: 1.12.0
  • Laravel Version: 8.83.6
  • PHP Version: 8.9.17
  • Database Driver & Version: MySQL / 8.0.28

Description:

I'm using an existing app with full Fortify Authentication, and I wanted to take advantage of the Two Factor Authentication as well. I've coded all the enabling / disabling part no problem and it all works great and sets the DB columns etc..., but the problem I'm having is that it refuses to challenge the user at login. I've asked everywhere and gotten no replies and spent about two days of my own time trying to debug this, so my last resort is to assume this is a bug of some kind. I've seen many other people complaining about this same exact issue when specifically implementing Fortify into an existing application, when doing it from a brand new Fortify app from scratch it magically works, and after hours of cross-referencing both I cannot see a difference between them, they are identical. So I'm very confused by what is causing this or if I'm just missing something incredibly small.

I've followed the docs, word-for-word, and done the standard like I've defined a custom view via;

       Fortify::twoFactorChallengeView(function () {
            return view('auth.two-factor-challenge');
        });

But when logging in it just logs the user in directly and doesn't even bother to challenge 2FA, even if they have it enabled. However, I did notice if I'm not logged in I can access the /two-factor-challenge route, but if I am logged in I can't access it and it just redirects back to index. Removed all my own custom middleware and left it strictly defaults and this was still the case so I'm not sure if this is how it's supposed to work? Seems a bit odd that a guest who isn't logged in can view the form to verify a 2FA code?

I set some dd()'s on AuthenticatedSessionController@loginPipeline and it passes through as expected and triggers RedirectIfTwoFactorAuthenticatable::class. However, when setting dd()'s in this class is where I start to notice some bizarre behaviour. It never makes it past the constructor, so my only conclusion is that it must be failing on the Auth guard somewhere? But I'm not using any custom auth guards, I'm using the default 'web'/'auth' auth guards, and I've not really changed anything or ovewritten anything so I'm a bit confused as to why it's not working.

I do have some custom logic inside my FortifyServiceProvider using authenticateUsing, but I don't think that should impact the 2FA challenge?

Steps To Reproduce:

Implement Fortify into an existing project and not a new one.

Happy to provide additional information as necessary, just can't really share the entire source code since it's an existing project for work which obviously contains other sensitive stuff. :)

Since this currently works in Jetstream I assume everything should be okay within Fortify. It's probably best that you dig into the Jetstream codebase to see how it's implemented there so you can port the implementation into your custom application. As for the rest, I'm sorry but we currently don't provide support with implementing Fortify on a custom app. It's best that you continue to try a support channel:

@driesvints

While I can understand you guys cannot provide support for custom apps given the amount of variables that can impact it, I think it is wrong to close this. I have looked at the Jetstream source code, and it helped me a lot with implementing the other parts of 2FA such as Enable/Disable and Recovery Codes.

But regarding the issue I've described, there is literally no difference between my app or Jetstream. I've read multiple other people complaining about similar issues regarding this with 2FA, that you guys just close and claim you're unable to help. I understand people are not entitled to support in open-source, but it really seems like you guys just refuse to acknowledge this could potentially be an issue despite many people complaining about it. Sure, it could turn out it's not a code issue and we all just somehow misconfigured it, but considering plenty of other people claim they followed the docs word for word (one of them being me), and are still having issues, that could ultimately mean that something vital is being left out of the docs that is crucial to the functionality of this feature, or there is a certain concept that simply isn't being explained properly or is explained in a way that people are misinterpreting it.

I appreciate you taking the time to reply, but I really think this is an issue and doesn't deserve to be closed as most of the support channels you've listed I've already mentioned this on, and no one really has any clue about what is causing this. I've spent multiple days myself trying to just figure out why it's failing to no avail, because the documentation is so limited on it, and when looking at source-code like Jetstream, my code is literally identical to it and the issue still persists.

I understand and respect the decision if you guys want to keep this closed, but given the frequency I've seen this brought up in various of the support channels you listed with no solid or concrete answers, I think it really is a genuine issue. Either way, I will keep this issue updated if I have any additional findings or find the cause of it.

@frequentredundancy okay, I'll try to help out but before I start can you give me a couple of links to Laracasts and Laravel.io forums where this question has been asked so I can check some of the replies?

@driesvints
Thanks for the offer to help Dries, and sorry for the late reply, got a bit carried away with what I explain below. For the links here is multiple from different places. Some found answers that worked for them, but some also didn't, and none of the answers provided on any of these links worked for me ;

However, I did actually manage to find the issue since posting my original reply. I went on a bit of a binge and I've found the issue that's caused this, it was an issue on my end, but I don't think the full blame falls on me and I definitely think it needs some clarification in the docs.

I previously mentioned I was using authenticateUsing. I thought how this worked was that it replaces specifically the authentication part of the pipeline, so I thought it wouldn't impact 2FA, since I assumed RedirectIfTwoFactorAuthenticatable::class would be retained. This is not the case, it replaced the entire pipeline I think. So, all default functionality was being erased and is why the 2FA redirect was not occuring since it was never hitting RedirectIfTwoFactorAuthenticatable::class.

I think this could use some clarification in the docs since I thought authenticateUsing would only replace specifically the authentication part of the pipeline that was responsible for grabbing/authenticating the user, where as authenticateThrough was what was used to replace the entire pipeline.

https://laravel.com/docs/9.x/fortify#customizing-user-authentication

There isn't much explanation of this in the docs. It's actually quite misleading and makes you think authenticateUsing is responsible for checking specifically if the login/credentials were valid, and not replacing the entire pipeline, and the example provided definitely reinforces this as well. I'm not sure if this is the intended functionaliy or if this is a bug/oversight, but if it is intended I definitely think just a warning/note should be added that informs developers using this functionality they will have to implement their own 2FA checks and/or pipeline stuff.

Since removing authenticateUsing and moving to authenticateThrough and defining my own pipeline, it has started working and everything seems to be working as intended now with some minor modifications.

Ah that's good that you find the cause @frequentredundancy. If you're willing, can you send in a PR to update the docs? There might indeed be some parts where we can explain better.

the problem still exists and not triggering on the login