2FA-Challenge: Fehlversuch crasht nicht mehr (Route two-factor.login fehlt)
Fortifys FailedTwoFactorLoginResponse leitet auf die Route two-factor.login um, die bei views => false nie registriert wird (RouteNotFoundException). Eigener Response leitet zurück auf die Volt-Challenge-Seite und meldet den Fehler auf Deutsch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
62fbafa4ce
commit
af9f238978
3 changed files with 65 additions and 0 deletions
31
app/Http/Responses/FailedTwoFactorChallengeResponse.php
Normal file
31
app/Http/Responses/FailedTwoFactorChallengeResponse.php
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Responses;
|
||||
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Laravel\Fortify\Contracts\FailedTwoFactorLoginResponse;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* Ersetzt Fortifys FailedTwoFactorLoginResponse: Der Standard leitet auf die
|
||||
* Fortify-Route `two-factor.login` um, die bei `views => false` nicht
|
||||
* registriert ist (RouteNotFoundException). Wir leiten stattdessen zurück auf
|
||||
* unsere Volt-Challenge-Seite.
|
||||
*/
|
||||
class FailedTwoFactorChallengeResponse implements FailedTwoFactorLoginResponse
|
||||
{
|
||||
public function toResponse($request): Response
|
||||
{
|
||||
[$key, $message] = $request->filled('recovery_code')
|
||||
? ['recovery_code', __('Der eingegebene Wiederherstellungs-Code ist ungültig.')]
|
||||
: ['code', __('Der eingegebene Code ist ungültig. Bitte versuchen Sie es mit einem aktuellen Code erneut.')];
|
||||
|
||||
if ($request->wantsJson()) {
|
||||
throw ValidationException::withMessages([
|
||||
$key => [$message],
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->route('two-factor.challenge')->withErrors([$key => $message]);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ use App\Actions\Fortify\CreateNewUser;
|
|||
use App\Actions\Fortify\ResetUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserPassword;
|
||||
use App\Actions\Fortify\UpdateUserProfileInformation;
|
||||
use App\Http\Responses\FailedTwoFactorChallengeResponse;
|
||||
use App\Http\Responses\RoleAwareLoginResponse;
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -13,6 +14,7 @@ use Illuminate\Support\Facades\RateLimiter;
|
|||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Fortify\Actions\RedirectIfTwoFactorAuthenticatable;
|
||||
use Laravel\Fortify\Contracts\FailedTwoFactorLoginResponse;
|
||||
use Laravel\Fortify\Contracts\LoginResponse;
|
||||
use Laravel\Fortify\Contracts\TwoFactorLoginResponse;
|
||||
use Laravel\Fortify\Fortify;
|
||||
|
|
@ -27,6 +29,9 @@ class FortifyServiceProvider extends ServiceProvider
|
|||
{
|
||||
$this->app->singleton(LoginResponse::class, RoleAwareLoginResponse::class);
|
||||
$this->app->singleton(TwoFactorLoginResponse::class, RoleAwareLoginResponse::class);
|
||||
// Fortifys Default leitet auf die nicht registrierte Route
|
||||
// `two-factor.login` (views => false) – zurück zur Volt-Challenge.
|
||||
$this->app->singleton(FailedTwoFactorLoginResponse::class, FailedTwoFactorChallengeResponse::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -78,6 +78,35 @@ test('a valid two-factor code completes login with a role-aware redirect', funct
|
|||
$this->assertAuthenticatedAs($customer);
|
||||
});
|
||||
|
||||
test('an invalid two-factor code returns to the challenge page with an error', function () {
|
||||
/** @var TestCase $this */
|
||||
$user = User::factory()->create(['is_active' => true]);
|
||||
enableTwoFactor($user);
|
||||
|
||||
$this->withSession(['login.id' => $user->id, 'login.remember' => false])
|
||||
->post('/two-factor-challenge', ['code' => '000000'])
|
||||
->assertRedirect(route('two-factor.challenge'))
|
||||
->assertSessionHasErrors('code');
|
||||
|
||||
$this->assertGuest();
|
||||
});
|
||||
|
||||
test('an invalid recovery code returns to the challenge page with an error', function () {
|
||||
/** @var TestCase $this */
|
||||
$user = User::factory()->create(['is_active' => true]);
|
||||
enableTwoFactor($user);
|
||||
$user->forceFill([
|
||||
'two_factor_recovery_codes' => encrypt(json_encode(['gueltiger-code'])),
|
||||
])->save();
|
||||
|
||||
$this->withSession(['login.id' => $user->id, 'login.remember' => false])
|
||||
->post('/two-factor-challenge', ['recovery_code' => 'falscher-code'])
|
||||
->assertRedirect(route('two-factor.challenge'))
|
||||
->assertSessionHasErrors('recovery_code');
|
||||
|
||||
$this->assertGuest();
|
||||
});
|
||||
|
||||
test('the fortify login post blocks inactive but verified users', function () {
|
||||
/** @var TestCase $this */
|
||||
$user = User::factory()->create(['is_active' => false]);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue