'Admin User', 'email' => 'admin@company.com', 'role' => 'admin', ]); $user = User::create([ 'name' => 'Standard User', 'email' => 'user@sentientgeeks.com', 'role' => 'user', ]); // Unauthenticated user is redirected to login $this->get('/admin/dashboard') ->assertRedirect(route('login')); // Admin can access admin dashboard $this->actingAs($admin) ->get('/admin/dashboard') ->assertStatus(200); // Standard user gets allowed standard user access to dashboard (our middleware handles this) $this->actingAs($user) ->get('/admin/dashboard') ->assertRedirect(route('dashboard')); } /** * Test blocked users are forced to logout and redirected. */ public function test_blocked_user_cannot_access_dashboard_and_gets_logged_out(): void { $user = User::create([ 'name' => 'Standard User', 'email' => 'user@sentientgeeks.com', 'role' => 'user', 'is_blocked' => true, ]); // Attempting to access dashboard logs them out and redirects $this->actingAs($user) ->get('/dashboard') ->assertRedirect(route('login')); $this->assertFalse(auth()->check()); } /** * Test restricted services are hidden from specific users via deny overrides. */ public function test_restricted_service_is_not_displayed_to_the_restricted_user(): void { $user = User::create([ 'name' => 'Standard User', 'email' => 'user@sentientgeeks.com', 'role' => 'user', ]); $app1 = App::create([ 'name' => 'Outlook', 'url' => 'https://outlook.office.com', 'color' => '#0078d4', 'tag' => 'Microsoft 365' ]); $app2 = App::create([ 'name' => 'Keka HR', 'url' => 'https://sentientgeeks.keka.com', 'color' => '#f27059', 'tag' => 'HR Portal' ]); // Create a role and associate both apps $role = Role::create(['name' => 'Employee']); $role->apps()->sync([$app1->id, $app2->id]); // Assign role to user $user->roles()->sync([$role->id]); // Restrict user from Keka HR using override UserAppOverride::create([ 'user_id' => $user->id, 'app_id' => $app2->id, 'type' => 'deny', ]); $response = $this->actingAs($user) ->get('/dashboard'); $response->assertStatus(200); $response->assertSee('Outlook'); $response->assertDontSee('Keka HR'); } /** * Test additional services are displayed to specific users via allow overrides. */ public function test_additional_service_is_displayed_to_the_user(): void { $user = User::create([ 'name' => 'Standard User', 'email' => 'user@sentientgeeks.com', 'role' => 'user', ]); $app1 = App::create([ 'name' => 'Outlook', 'url' => 'https://outlook.office.com', 'color' => '#0078d4', 'tag' => 'Microsoft 365' ]); $app2 = App::create([ 'name' => 'Keka HR', 'url' => 'https://sentientgeeks.keka.com', 'color' => '#f27059', 'tag' => 'HR Portal' ]); // Create a role that only has Outlook $role = Role::create(['name' => 'Intern']); $role->apps()->sync([$app1->id]); // Assign role to user $user->roles()->sync([$role->id]); // Add Keka HR as extra service using override UserAppOverride::create([ 'user_id' => $user->id, 'app_id' => $app2->id, 'type' => 'allow', ]); $response = $this->actingAs($user) ->get('/dashboard'); $response->assertStatus(200); $response->assertSee('Outlook'); $response->assertSee('Keka HR'); } /** * Test admin user cannot authenticate via Microsoft OAuth callback. */ public function test_admin_cannot_authenticate_via_microsoft_oauth_callback(): void { $admin = User::create([ 'name' => 'Admin User', 'email' => 'admin@company.com', 'role' => 'admin', 'microsoft_id' => 'admin-microsoft-id-999' ]); $mockSocialite = \Mockery::mock('Laravel\Socialite\Contracts\Provider'); $mockUser = \Mockery::mock('Laravel\Socialite\Two\User'); $mockUser->shouldReceive('getId')->andReturn('admin-microsoft-id-999'); $mockUser->shouldReceive('getEmail')->andReturn('admin@company.com'); $mockUser->shouldReceive('getName')->andReturn('Admin User'); $mockUser->shouldReceive('getAvatar')->andReturn(null); $mockSocialite->shouldReceive('user')->andReturn($mockUser); \Laravel\Socialite\Facades\Socialite::shouldReceive('driver')->with('microsoft')->andReturn($mockSocialite); $response = $this->get('/auth/microsoft/callback'); $response->assertRedirect(route('admin.login')); $response->assertSessionHas('error', 'Security protocol: Administrators are restricted to email and password authentication only.'); $this->assertFalse(auth()->check()); } /** * Test local logout redirects to Microsoft global logout endpoint. */ public function test_user_logout_redirects_to_microsoft_logout_page(): void { $user = User::create([ 'name' => 'Standard User', 'email' => 'user@sentientgeeks.com', 'role' => 'user', ]); $mockSocialite = \Mockery::mock('Laravel\Socialite\Contracts\Provider'); $mockSocialite->shouldReceive('getLogoutUrl') ->with(route('login')) ->andReturn('https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=' . urlencode(route('login'))); \Laravel\Socialite\Facades\Socialite::shouldReceive('driver')->with('microsoft')->andReturn($mockSocialite); $response = $this->actingAs($user) ->get('/logout'); // supports GET for testing $response->assertRedirect('https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri=' . urlencode(route('login'))); $this->assertFalse(auth()->check()); } /** * Test Microsoft Front-channel logout callback terminates local session. */ public function test_microsoft_front_channel_logout_clears_session(): void { $user = User::create([ 'name' => 'Standard User', 'email' => 'user@sentientgeeks.com', 'role' => 'user', ]); $this->actingAs($user); $this->assertTrue(auth()->check()); $response = $this->get('/auth/microsoft/logout'); $response->assertStatus(200); $response->assertSee('Logged out from SingleLogin'); $this->assertFalse(auth()->check()); } /** * Test that launching any service (like Keka) routes through Microsoft SSO flow * if the user is Microsoft-linked. */ public function test_sso_launch_redirects_to_microsoft_for_all_services_if_user_is_microsoft_linked(): void { $user = User::create([ 'name' => 'Standard User', 'email' => 'user@sentientgeeks.com', 'role' => 'user', 'microsoft_id' => 'user-microsoft-id-123', ]); $app = App::create([ 'name' => 'Keka HR', 'url' => 'https://sentientgeeks.keka.com', 'color' => '#f27059', 'tag' => 'HR Portal' ]); // Assign role with the app to user $role = Role::create(['name' => 'Employee']); $role->apps()->sync([$app->id]); $user->roles()->sync([$role->id]); $mockSocialite = \Mockery::mock('Laravel\Socialite\Contracts\Provider'); $mockSocialite->shouldReceive('redirectUrl')->with(route('sso.callback'))->andReturnSelf(); $mockSocialite->shouldReceive('with')->with([ 'login_hint' => $user->email, 'domain_hint' => 'organizations' ])->andReturnSelf(); $mockSocialite->shouldReceive('redirect') ->andReturn(redirect('https://login.microsoftonline.com/common/oauth2/v2.0/authorize')); \Laravel\Socialite\Facades\Socialite::shouldReceive('driver')->with('microsoft')->andReturn($mockSocialite); $response = $this->actingAs($user) ->get(route('sso.launch', $app->id)); $response->assertRedirect('https://login.microsoftonline.com/common/oauth2/v2.0/authorize'); } }