feat(2fa): onboarding no longer forces 2FA (only password rotation)
parent
9a01bfedf7
commit
82d5644767
|
|
@ -7,8 +7,8 @@ use Illuminate\Http\Request;
|
|||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* After login, force the security onboarding before the panel is reachable:
|
||||
* 1) rotate the seeded password, then 2) enrol 2FA.
|
||||
* After login, force the seeded-password rotation before the panel is reachable.
|
||||
* 2FA is optional (offered in Settings), so it is NOT forced here.
|
||||
*/
|
||||
class EnsureSecurityOnboarded
|
||||
{
|
||||
|
|
@ -16,16 +16,8 @@ class EnsureSecurityOnboarded
|
|||
{
|
||||
$user = $request->user();
|
||||
|
||||
if ($user) {
|
||||
$allowed = $request->routeIs('password.change', 'two-factor.setup', 'logout');
|
||||
|
||||
if ($user->must_change_password && ! $request->routeIs('password.change', 'logout')) {
|
||||
return redirect()->route('password.change');
|
||||
}
|
||||
|
||||
if (! $user->must_change_password && ! $user->hasTwoFactorEnabled() && ! $allowed) {
|
||||
return redirect()->route('two-factor.setup');
|
||||
}
|
||||
if ($user && $user->must_change_password && ! $request->routeIs('password.change', 'logout')) {
|
||||
return redirect()->route('password.change');
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ class PasswordChange extends Component
|
|||
'must_change_password' => false,
|
||||
])->save();
|
||||
|
||||
// onboarding continues: the middleware sends an un-enrolled user to 2FA setup.
|
||||
return $this->redirect(route('two-factor.setup'), navigate: true);
|
||||
// 2FA is optional now — go straight to the panel; 2FA is offered in Settings.
|
||||
return $this->redirect(route('dashboard'), navigate: true);
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Livewire\Auth\PasswordChange;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Livewire;
|
||||
use Tests\TestCase;
|
||||
|
||||
class OptionalOnboardingTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_rotated_user_without_2fa_reaches_the_dashboard(): void
|
||||
{
|
||||
$user = User::factory()->create(['must_change_password' => false]);
|
||||
|
||||
$this->actingAs($user)->get('/')->assertOk();
|
||||
}
|
||||
|
||||
public function test_user_that_must_change_password_is_still_redirected(): void
|
||||
{
|
||||
$user = User::factory()->create(['must_change_password' => true]);
|
||||
|
||||
$this->actingAs($user)->get('/')->assertRedirect(route('password.change'));
|
||||
}
|
||||
|
||||
public function test_password_change_lands_on_dashboard_not_2fa_setup(): void
|
||||
{
|
||||
$user = User::factory()->create(['must_change_password' => true, 'password' => bcrypt('old-Password-1')]);
|
||||
|
||||
Livewire::actingAs($user)->test(PasswordChange::class)
|
||||
->set('current', 'old-Password-1')
|
||||
->set('password', 'new-Password-123')
|
||||
->set('password_confirmation', 'new-Password-123')
|
||||
->call('update')
|
||||
->assertRedirect(route('dashboard'));
|
||||
}
|
||||
|
||||
public function test_broadcast_gate_passes_on_password_rotation_alone(): void
|
||||
{
|
||||
$user = User::factory()->create(['must_change_password' => false]);
|
||||
|
||||
$this->assertTrue($user->securityOnboarded());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue