Reputation: 801
I've used Laravel Fortify to write some authentication for my app and I've setup the enable part of the 2FA, and that all works fine, but the problem I'm having is that it doesn't seem to trigger the challenge when a user logs in?
I've setup the custom view like so;
Fortify::twoFactorChallengeView(function () {
return view('auth.two-factor-challenge');
});
and Fortify claims it should "...automatically redirect the user to your application's two factor authentication challenge screen." (https://laravel.com/docs/9.x/fortify#authenticating-with-two-factor-authentication), but this is not the case for me, it doesn't redirect at all.
Can't seem to find any sort of Middleware in the source-code to manually achieve this, so was wondering if someone might have an idea of what's going on?
I've manually checked my DB and all the two factor columns such as two_factor_secret
are set correctly after enabling, so I'm a bit confused.
In my fortify config, I've got the below set since I don't want to confirm password and instead confirm the current OTP code for any changes that need to be made since that is what makes the most sense for my app I think. Not sure if disabling confirmPassword
would cause this though?
Features::twoFactorAuthentication([
'confirm' => true,
'confirmPassword' => false,
]),
Upvotes: 6
Views: 4568
Reputation: 1
I have found the solution for this problem. Comment Auth::routes()
in your routes/web.php
.
Upvotes: 0
Reputation: 1861
I also hit this problem, in my case I was migrating from Breeze to Jetstream. In either case, make sure you are implementing Fortify's pipeline, as seen in this Github issue.
I've copied a working implementation below of app/Http/Controllers/Auth/AuthenticatedSessionController.php
:
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Pipeline\Pipeline;
use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Actions\AttemptToAuthenticate;
use Laravel\Fortify\Actions\EnsureLoginIsNotThrottled;
use Laravel\Fortify\Actions\PrepareAuthenticatedSession;
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
use Laravel\Fortify\Contracts\LoginResponse;
use Laravel\Fortify\Features;
use Laravel\Fortify\Fortify;
use Laravel\Fortify\Http\Requests\LoginRequest;
class AuthenticatedSessionController extends Controller
{
/**
* Display the login view.
*
* @return \Illuminate\View\View
*/
public function create()
{
return view('auth.login');
}
/**
* Attempt to authenticate a new session.
*
* @param \Laravel\Fortify\Http\Requests\LoginRequest $request
* @return mixed
*/
public function store(LoginRequest $request)
{
return $this->loginPipeline($request)->then(function ($request) {
return app(LoginResponse::class);
});
}
/**
* Get the authentication pipeline instance.
*
* @param \Laravel\Fortify\Http\Requests\LoginRequest $request
* @return \Illuminate\Pipeline\Pipeline
*/
protected function loginPipeline(LoginRequest $request)
{
if (Fortify::$authenticateThroughCallback) {
return (new Pipeline(app()))->send($request)->through(array_filter(
call_user_func(Fortify::$authenticateThroughCallback, $request)
));
}
if (is_array(config('fortify.pipelines.login'))) {
return (new Pipeline(app()))->send($request)->through(array_filter(
config('fortify.pipelines.login')
));
}
return (new Pipeline(app()))->send($request)->through(array_filter([
config('fortify.limiters.login') ? null : EnsureLoginIsNotThrottled::class,
Features::enabled(Features::twoFactorAuthentication()) ? RedirectIfTwoFactorAuthenticatable::class : null,
AttemptToAuthenticate::class,
PrepareAuthenticatedSession::class,
]));
}
/**
* Destroy an authenticated session.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Request $request)
{
Auth::guard('web')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
}
Upvotes: 2
Reputation: 21
if you are using laravel 10 you can comment confirm in your config/fortify.php
Features::twoFactorAuthentication([
//'confirm' => true,
'confirmPassword' => true,
// 'window' => 0,
]),
Upvotes: 2
Reputation: 21
I have found a solution that is working fine.
When you do post a request and see the response to request it will return the:
> {"two_factor":true}
So make a check if two_factor == true
then show two-factor challenge page.
This is the best solution as there is no other solution.
Upvotes: 0
Reputation: 21
Just encountered this issue today and been searching for a solution in the Internet all day. Then I came across this article (https://epndavis.com/blog/laravel-fortify-two-factor-authentication/) which shows that the confirm
attribute is not included in one of its snippets. Fortunate enough, after trying it on my end, logging in FINALLY triggers the 2FA challenge.
Therefore, your code should now look like this:
Features::twoFactorAuthentication([
'confirmPassword' => false,
]),
In case you already solved this, I hope this answer would help others resolve this issue and move on to the other parts of their development.
PS. As a replacement for confirm
, I'd recommend visiting this article: https://dev.to/nicolus/laravel-fortify-implement-2fa-in-a-way-that-won-t-let-users-lock-themselves-out-2ejk
Working example: https://github.com/xyberpastoril/PCBMS/pull/6
Upvotes: 2