getProperty('resolvedSettings'); $prop->setAccessible(true); $prop->setValue(null, null); Cache::flush(); Role::firstOrCreate(['name' => 'User', 'guard_name' => 'web']); }); function enableOauth(string $provider): void { app(SystemConfigService::class)->update(['feature_'.$provider.'_oauth' => true]); } function fakeSocialiteUser(array $overrides = []): SocialiteUserContract { $u = new Laravel\Socialite\Two\User; $u->id = $overrides['id'] ?? 'oauth-id-123'; $u->name = $overrides['name'] ?? 'OAuth User'; $u->email = $overrides['email'] ?? 'oauth@example.com'; $u->avatar = $overrides['avatar'] ?? 'https://example.com/avatar.png'; $u->user = $overrides['user'] ?? []; return $u; } test('redirect returns 404 when provider feature is disabled', function () { $this->get('/auth/google')->assertNotFound(); }); test('redirect issues a redirect when provider feature is enabled', function () { enableOauth('google'); Socialite::shouldReceive('driver->redirect') ->andReturn(redirect('https://accounts.google.com/o/oauth2/auth?fake=1')); $this->get('/auth/google')->assertRedirect(); expect(session('social_auth_provider'))->toBe('google'); }); test('callback without provider session redirects to login with error', function () { $this->get('/auth/callback') ->assertRedirect('/login') ->assertSessionHas('error'); }); test('callback rejects unverified email from provider', function () { enableOauth('google'); session(['social_auth_provider' => 'google']); Socialite::shouldReceive('driver->user')->andReturn(fakeSocialiteUser([ 'user' => ['email_verified' => false], ])); $this->get('/auth/callback') ->assertRedirect('/login') ->assertSessionHas('error'); $this->assertGuest(); }); test('callback creates a new user via provider id and assigns user role', function () { enableOauth('google'); session(['social_auth_provider' => 'google']); Socialite::shouldReceive('driver->user')->andReturn(fakeSocialiteUser([ 'id' => 'google-uid-9', 'email' => 'fresh@example.com', 'name' => 'Fresh User', ])); $this->get('/auth/callback')->assertRedirect('/dashboard'); $user = User::where('email', 'fresh@example.com')->first(); expect($user)->not->toBeNull(); expect($user->google_id)->toBe('google-uid-9'); expect($user->hasRole('User'))->toBeTrue(); }); test('callback links to existing user with matching email when no provider id yet', function () { enableOauth('google'); session(['social_auth_provider' => 'google']); $existing = User::factory()->create([ 'email' => 'link@example.com', 'google_id' => null, ]); Socialite::shouldReceive('driver->user')->andReturn(fakeSocialiteUser([ 'id' => 'google-uid-link', 'email' => 'link@example.com', ])); $this->get('/auth/callback')->assertRedirect('/dashboard'); expect($existing->fresh()->google_id)->toBe('google-uid-link'); $this->assertAuthenticatedAs($existing->fresh()); }); test('callback refuses to overwrite a different existing oauth identity', function () { enableOauth('google'); session(['social_auth_provider' => 'google']); $existing = User::factory()->create([ 'email' => 'taken@example.com', 'google_id' => 'different-google-id', ]); Socialite::shouldReceive('driver->user')->andReturn(fakeSocialiteUser([ 'id' => 'attacker-id', 'email' => 'taken@example.com', ])); $this->get('/auth/callback') ->assertRedirect('/login') ->assertSessionHas('error'); expect($existing->fresh()->google_id)->toBe('different-google-id'); $this->assertGuest(); }); test('callback re-uses user matched by provider id', function () { enableOauth('google'); session(['social_auth_provider' => 'google']); $existing = User::factory()->create(['google_id' => 'stable-id']); Socialite::shouldReceive('driver->user')->andReturn(fakeSocialiteUser([ 'id' => 'stable-id', 'email' => $existing->email, ])); $this->get('/auth/callback')->assertRedirect('/dashboard'); $this->assertAuthenticatedAs($existing->fresh()); }); test('callback on socialite exception redirects to login with error', function () { enableOauth('google'); session(['social_auth_provider' => 'google']); Socialite::shouldReceive('driver->user')->andThrow(new Exception('OAuth boom')); $this->get('/auth/callback') ->assertRedirect('/login') ->assertSessionHas('error'); $this->assertGuest(); });