Initial commit
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Security\Authorization;
|
||||
|
||||
use App\Http\Livewire\Mailings\Manage as MailingsManage;
|
||||
use App\Http\Livewire\Profiles\Create as ProfilesCreate;
|
||||
use App\Http\Livewire\Tags\Create as TagsCreate;
|
||||
use App\Models\Admin;
|
||||
use App\Models\Bank;
|
||||
use App\Models\Organization;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Livewire\Livewire;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Livewire Method-Level Authorization Tests
|
||||
*
|
||||
* Tests critical method-level authorization to prevent Livewire direct method invocation attacks.
|
||||
* Focuses on the two newly discovered critical vulnerabilities and authorization patterns.
|
||||
*
|
||||
* @group security
|
||||
* @group authorization
|
||||
* @group livewire
|
||||
* @group critical
|
||||
*/
|
||||
class LivewireMethodAuthorizationTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
// ===========================================
|
||||
// TAGS/CREATE.PHP - AUTHORIZATION TESTS
|
||||
// ===========================================
|
||||
|
||||
/** @test */
|
||||
public function admin_can_call_tags_create_method()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$this->actingAs($admin, 'admin');
|
||||
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(200);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function central_bank_can_call_tags_create_method()
|
||||
{
|
||||
$bank = Bank::factory()->create(['level' => 0]);
|
||||
$this->actingAs($bank, 'bank');
|
||||
session(['activeProfileType' => Bank::class, 'activeProfileId' => $bank->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(200);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function regular_bank_cannot_call_tags_create_method()
|
||||
{
|
||||
$bank = Bank::factory()->create(['level' => 1]);
|
||||
$this->actingAs($bank, 'bank');
|
||||
session(['activeProfileType' => Bank::class, 'activeProfileId' => $bank->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function user_cannot_call_tags_create_method()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->actingAs($user, 'web');
|
||||
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function organization_cannot_call_tags_create_method()
|
||||
{
|
||||
$org = Organization::factory()->create();
|
||||
$this->actingAs($org, 'organization');
|
||||
session(['activeProfileType' => Organization::class, 'activeProfileId' => $org->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
// PROFILES/CREATE.PHP - CRITICAL VULNERABILITY FIX
|
||||
// This was a CRITICAL vulnerability - unauthorized profile creation
|
||||
// ===========================================
|
||||
|
||||
/** @test */
|
||||
public function admin_can_access_profiles_create_component()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$this->actingAs($admin, 'admin');
|
||||
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin->id]);
|
||||
|
||||
$component = Livewire::test(ProfilesCreate::class);
|
||||
|
||||
$component->assertStatus(200);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function central_bank_can_access_profiles_create_component()
|
||||
{
|
||||
$bank = Bank::factory()->create(['level' => 0]);
|
||||
$this->actingAs($bank, 'bank');
|
||||
session(['activeProfileType' => Bank::class, 'activeProfileId' => $bank->id]);
|
||||
|
||||
$component = Livewire::test(ProfilesCreate::class);
|
||||
|
||||
$component->assertStatus(200);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function user_cannot_access_profiles_create_component()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->actingAs($user, 'web');
|
||||
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
|
||||
|
||||
$component = Livewire::test(ProfilesCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function organization_cannot_access_profiles_create_component()
|
||||
{
|
||||
$org = Organization::factory()->create();
|
||||
$this->actingAs($org, 'organization');
|
||||
session(['activeProfileType' => Organization::class, 'activeProfileId' => $org->id]);
|
||||
|
||||
$component = Livewire::test(ProfilesCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
// MAILINGS/MANAGE.PHP - CRITICAL VULNERABILITY FIX
|
||||
// bulkDeleteMailings() method was unprotected
|
||||
// ===========================================
|
||||
|
||||
/** @test */
|
||||
public function admin_can_access_mailings_manage_component()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$this->actingAs($admin, 'admin');
|
||||
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin->id]);
|
||||
|
||||
$component = Livewire::test(MailingsManage::class);
|
||||
|
||||
$component->assertStatus(200);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function central_bank_can_access_mailings_manage_component()
|
||||
{
|
||||
$bank = Bank::factory()->create(['level' => 0]);
|
||||
$this->actingAs($bank, 'bank');
|
||||
session(['activeProfileType' => Bank::class, 'activeProfileId' => $bank->id]);
|
||||
|
||||
$component = Livewire::test(MailingsManage::class);
|
||||
|
||||
$component->assertStatus(200);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function user_cannot_access_mailings_manage_component()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->actingAs($user, 'web');
|
||||
session(['activeProfileType' => User::class, 'activeProfileId' => $user->id]);
|
||||
|
||||
$component = Livewire::test(MailingsManage::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function organization_cannot_access_mailings_manage_component()
|
||||
{
|
||||
$org = Organization::factory()->create();
|
||||
$this->actingAs($org, 'organization');
|
||||
session(['activeProfileType' => Organization::class, 'activeProfileId' => $org->id]);
|
||||
|
||||
$component = Livewire::test(MailingsManage::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
// CROSS-GUARD ATTACK PREVENTION TESTS
|
||||
// ===========================================
|
||||
|
||||
/** @test */
|
||||
public function user_authenticated_on_wrong_guard_cannot_access_admin_components()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->actingAs($user, 'web');
|
||||
|
||||
// Try to fake being an admin by setting wrong session
|
||||
$admin = Admin::factory()->create();
|
||||
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin->id]);
|
||||
|
||||
// Should be blocked because guard doesn't match
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function admin_cannot_access_other_admins_session()
|
||||
{
|
||||
$admin1 = Admin::factory()->create();
|
||||
$admin2 = Admin::factory()->create();
|
||||
|
||||
$this->actingAs($admin1, 'admin');
|
||||
// Try to fake session to access admin2's context
|
||||
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin2->id]);
|
||||
|
||||
// Should be blocked by ProfileAuthorizationHelper IDOR prevention
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function unauthenticated_user_cannot_access_admin_components()
|
||||
{
|
||||
// No authentication at all - expect redirect or 403
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function user_with_no_session_cannot_access_admin_components()
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$this->actingAs($user, 'web');
|
||||
// Don't set session variables - this simulates a corrupted or missing session
|
||||
|
||||
// Set minimal session to prevent "No active profile" error
|
||||
// but make it point to a non-existent or wrong profile
|
||||
session([
|
||||
'activeProfileType' => User::class,
|
||||
'activeProfileId' => $user->id,
|
||||
'active_guard' => 'web',
|
||||
]);
|
||||
|
||||
// User (web guard) should not be able to access admin components
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
// AUTHORIZATION CACHING TESTS
|
||||
// ===========================================
|
||||
|
||||
/** @test */
|
||||
public function authorization_is_cached_within_same_request()
|
||||
{
|
||||
$admin = Admin::factory()->create();
|
||||
$this->actingAs($admin, 'admin');
|
||||
session(['activeProfileType' => Admin::class, 'activeProfileId' => $admin->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
// First check happens in mount()
|
||||
$component->assertStatus(200);
|
||||
|
||||
// Component can be used multiple times - caching works
|
||||
$component->assertStatus(200);
|
||||
}
|
||||
|
||||
// ===========================================
|
||||
// BANK LEVEL VALIDATION TESTS
|
||||
// ===========================================
|
||||
|
||||
/** @test */
|
||||
public function only_central_bank_level_zero_can_access_admin_functions()
|
||||
{
|
||||
// Test level 0 (central bank) - should work
|
||||
$centralBank = Bank::factory()->create(['level' => 0]);
|
||||
$this->actingAs($centralBank, 'bank');
|
||||
session(['activeProfileType' => Bank::class, 'activeProfileId' => $centralBank->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
$component->assertStatus(200);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function bank_level_one_cannot_access_admin_functions()
|
||||
{
|
||||
$bank = Bank::factory()->create(['level' => 1]);
|
||||
$this->actingAs($bank, 'bank');
|
||||
session(['activeProfileType' => Bank::class, 'activeProfileId' => $bank->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function bank_level_two_cannot_access_admin_functions()
|
||||
{
|
||||
$bank = Bank::factory()->create(['level' => 2]);
|
||||
$this->actingAs($bank, 'bank');
|
||||
session(['activeProfileType' => Bank::class, 'activeProfileId' => $bank->id]);
|
||||
|
||||
$component = Livewire::test(TagsCreate::class);
|
||||
|
||||
$component->assertStatus(403);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user