From e6d3e3f3fd77f1393440b8b2a060d4d991a56ffc Mon Sep 17 00:00:00 2001 From: Grigory Frolov <2168057+gynsus@users.noreply.github.com> Date: Sun, 30 Aug 2026 13:47:55 +0300 Subject: [PATCH 1/7] fix: force Meta page re-selection on connect via auth_type=rerequest --- app/Http/Controllers/Auth/FacebookController.php | 3 +++ app/Http/Controllers/Auth/InstagramFacebookController.php | 3 +++ tests/Feature/Social/FacebookControllerTest.php | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/app/Http/Controllers/Auth/FacebookController.php b/app/Http/Controllers/Auth/FacebookController.php index 8142f6f8f..6b9b6a019 100644 --- a/app/Http/Controllers/Auth/FacebookController.php +++ b/app/Http/Controllers/Auth/FacebookController.php @@ -51,6 +51,9 @@ public function connect(Request $request): Response Socialite::driver($this->driver) ->usingGraphVersion($this->graphVersion()) ->setScopes($this->scopes) + // Meta silently reuses the previous grant (and its page selection), + // so without rerequest a newly created Page never shows up. + ->with(['auth_type' => 'rerequest']) ->redirect() ->getTargetUrl() ); diff --git a/app/Http/Controllers/Auth/InstagramFacebookController.php b/app/Http/Controllers/Auth/InstagramFacebookController.php index d20d32712..a4c9b4a40 100644 --- a/app/Http/Controllers/Auth/InstagramFacebookController.php +++ b/app/Http/Controllers/Auth/InstagramFacebookController.php @@ -65,6 +65,9 @@ public function connect(Request $request): Response ->usingGraphVersion($this->graphVersion()) ->setScopes($this->scopes) ->redirectUrl(route('app.social.instagram-facebook.callback')) + // Meta silently reuses the previous grant (and its page selection), + // so without rerequest a newly created Page never shows up. + ->with(['auth_type' => 'rerequest']) ->redirect() ->getTargetUrl(); diff --git a/tests/Feature/Social/FacebookControllerTest.php b/tests/Feature/Social/FacebookControllerTest.php index 8b3e627db..885c66f49 100644 --- a/tests/Feature/Social/FacebookControllerTest.php +++ b/tests/Feature/Social/FacebookControllerTest.php @@ -27,6 +27,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); $driverMock->shouldReceive('setScopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with(['auth_type' => 'rerequest'])->once()->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', ])); @@ -646,6 +647,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); $driverMock->shouldReceive('setScopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with(['auth_type' => 'rerequest'])->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', ])); @@ -673,6 +675,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); $driverMock->shouldReceive('setScopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with(['auth_type' => 'rerequest'])->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', ])); @@ -699,6 +702,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); $driverMock->shouldReceive('setScopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with(['auth_type' => 'rerequest'])->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', ])); From 64292b26d12dbc6208acb0476da2bde46b142208 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Tue, 8 Sep 2026 10:57:16 -0300 Subject: [PATCH 2/7] Use Socialite's reRequest() for the Meta connect flows FacebookProvider already exposes reRequest(), which sets exactly the auth_type=rerequest field the connect flows need. Calling it directly replaces with(['auth_type' => 'rerequest']) and drops the comment the raw parameter needed, since the method name carries the intent. It also avoids a footgun: AbstractProvider::with() assigns $parameters rather than merging into them, so a second with() anywhere in the chain would have silently dropped auth_type. Cover InstagramFacebookController@connect, which had no test at all, so both halves of the fix are verified rather than just the Facebook one. --- .../Controllers/Auth/FacebookController.php | 4 +--- .../Auth/InstagramFacebookController.php | 4 +--- .../Feature/Social/FacebookControllerTest.php | 8 +++---- .../InstagramFacebookControllerTest.php | 23 +++++++++++++++++++ 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/app/Http/Controllers/Auth/FacebookController.php b/app/Http/Controllers/Auth/FacebookController.php index 6b9b6a019..a153e81e5 100644 --- a/app/Http/Controllers/Auth/FacebookController.php +++ b/app/Http/Controllers/Auth/FacebookController.php @@ -51,9 +51,7 @@ public function connect(Request $request): Response Socialite::driver($this->driver) ->usingGraphVersion($this->graphVersion()) ->setScopes($this->scopes) - // Meta silently reuses the previous grant (and its page selection), - // so without rerequest a newly created Page never shows up. - ->with(['auth_type' => 'rerequest']) + ->reRequest() ->redirect() ->getTargetUrl() ); diff --git a/app/Http/Controllers/Auth/InstagramFacebookController.php b/app/Http/Controllers/Auth/InstagramFacebookController.php index a4c9b4a40..6f2a2af94 100644 --- a/app/Http/Controllers/Auth/InstagramFacebookController.php +++ b/app/Http/Controllers/Auth/InstagramFacebookController.php @@ -65,9 +65,7 @@ public function connect(Request $request): Response ->usingGraphVersion($this->graphVersion()) ->setScopes($this->scopes) ->redirectUrl(route('app.social.instagram-facebook.callback')) - // Meta silently reuses the previous grant (and its page selection), - // so without rerequest a newly created Page never shows up. - ->with(['auth_type' => 'rerequest']) + ->reRequest() ->redirect() ->getTargetUrl(); diff --git a/tests/Feature/Social/FacebookControllerTest.php b/tests/Feature/Social/FacebookControllerTest.php index 885c66f49..5c30e3122 100644 --- a/tests/Feature/Social/FacebookControllerTest.php +++ b/tests/Feature/Social/FacebookControllerTest.php @@ -27,7 +27,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); $driverMock->shouldReceive('setScopes')->andReturnSelf(); - $driverMock->shouldReceive('with')->with(['auth_type' => 'rerequest'])->once()->andReturnSelf(); + $driverMock->shouldReceive('reRequest')->once()->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', ])); @@ -647,7 +647,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); $driverMock->shouldReceive('setScopes')->andReturnSelf(); - $driverMock->shouldReceive('with')->with(['auth_type' => 'rerequest'])->andReturnSelf(); + $driverMock->shouldReceive('reRequest')->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', ])); @@ -675,7 +675,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); $driverMock->shouldReceive('setScopes')->andReturnSelf(); - $driverMock->shouldReceive('with')->with(['auth_type' => 'rerequest'])->andReturnSelf(); + $driverMock->shouldReceive('reRequest')->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', ])); @@ -702,7 +702,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); $driverMock->shouldReceive('setScopes')->andReturnSelf(); - $driverMock->shouldReceive('with')->with(['auth_type' => 'rerequest'])->andReturnSelf(); + $driverMock->shouldReceive('reRequest')->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', ])); diff --git a/tests/Feature/Social/InstagramFacebookControllerTest.php b/tests/Feature/Social/InstagramFacebookControllerTest.php index 56d8414e9..ad11d10b3 100644 --- a/tests/Feature/Social/InstagramFacebookControllerTest.php +++ b/tests/Feature/Social/InstagramFacebookControllerTest.php @@ -22,6 +22,29 @@ $this->workspace->members()->attach($this->user->id, ['role' => Role::Member->value]); }); +test('instagram-facebook connect redirects to oauth provider', function () { + $driverMock = Mockery::mock(); + $driverMock->shouldReceive('usingGraphVersion')->andReturnSelf(); + $driverMock->shouldReceive('setScopes')->andReturnSelf(); + $driverMock->shouldReceive('redirectUrl')->andReturnSelf(); + $driverMock->shouldReceive('reRequest')->once()->andReturnSelf(); + $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ + 'getTargetUrl' => 'https://www.facebook.com/v25.0/dialog/oauth?test=1', + ])); + + Socialite::shouldReceive('driver') + ->with('facebook') + ->andReturn($driverMock); + + $response = $this->actingAs($this->user) + ->withHeader('X-Inertia', 'true') + ->get(route('app.social.instagram-facebook.connect')); + + $response->assertStatus(409); // Inertia::location returns 409 with X-Inertia header + + expect(session('social_connect_workspace'))->toBe($this->workspace->id); +}); + test('instagram-facebook callback follows accounts pagination and shows picker', function () { session([ 'social_connect_workspace' => $this->workspace->id, From 6dc191c67c4572a6f1152f02bdc42bc7311e6aa0 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Tue, 8 Sep 2026 10:57:23 -0300 Subject: [PATCH 3/7] Force TikTok's authorization screen with disable_auto_auth TikTok skips the authorization page whenever the browser holds a valid session and the app was authorized before, handing back a code for whoever happens to be logged in. A user who wants to connect a different account never reaches the account chooser; the only way out is logging out of TikTok in the browser first. Same class of trap as Meta reusing its page selection, different mechanism. Login Kit documents disable_auto_auth for this: 0 skips the page for valid sessions, 1 always shows it. redirectToProvider() had no way to pass extra authorize-URL parameters, so it takes an optional array now. It only calls with() when that array is non-empty, leaving the Discord, Pinterest and X redirects byte for byte as they were. --- app/Http/Controllers/Auth/SocialController.php | 17 ++++++++++++----- app/Http/Controllers/Auth/TikTokController.php | 4 +++- tests/Feature/Social/TikTokControllerTest.php | 2 ++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Auth/SocialController.php b/app/Http/Controllers/Auth/SocialController.php index b63de0409..204a14216 100644 --- a/app/Http/Controllers/Auth/SocialController.php +++ b/app/Http/Controllers/Auth/SocialController.php @@ -206,17 +206,24 @@ protected function filterConnectableIdentities( )->values()->all(); } - protected function redirectToProvider(Request $request, string $driver, array $scopes): SymfonyResponse + /** + * @param array $scopes + * @param array $parameters Extra query parameters for the provider's authorize URL. + */ + protected function redirectToProvider(Request $request, string $driver, array $scopes, array $parameters = []): SymfonyResponse { $workspace = $request->user()->currentWorkspace; $this->rememberConnectSession($request, $workspace); + $provider = Socialite::driver($driver)->scopes($scopes); + + if ($parameters !== []) { + $provider->with($parameters); + } + return Inertia::location( - Socialite::driver($driver) - ->scopes($scopes) - ->redirect() - ->getTargetUrl() + $provider->redirect()->getTargetUrl() ); } diff --git a/app/Http/Controllers/Auth/TikTokController.php b/app/Http/Controllers/Auth/TikTokController.php index 88b678a57..8e39b59ac 100644 --- a/app/Http/Controllers/Auth/TikTokController.php +++ b/app/Http/Controllers/Auth/TikTokController.php @@ -37,7 +37,9 @@ public function connect(Request $request): Response $this->authorize('manageAccounts', $workspace); - return $this->redirectToProvider($request, $this->driver, $this->scopes); + return $this->redirectToProvider($request, $this->driver, $this->scopes, [ + 'disable_auto_auth' => 1, + ]); } public function callback(Request $request): InertiaResponse diff --git a/tests/Feature/Social/TikTokControllerTest.php b/tests/Feature/Social/TikTokControllerTest.php index c95218502..2e91da566 100644 --- a/tests/Feature/Social/TikTokControllerTest.php +++ b/tests/Feature/Social/TikTokControllerTest.php @@ -22,6 +22,7 @@ test('tiktok connect redirects to oauth provider', function () { $driverMock = Mockery::mock(); $driverMock->shouldReceive('scopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with(['disable_auto_auth' => 1])->once()->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.tiktok.com/v2/auth/authorize?test=1', ])); @@ -193,6 +194,7 @@ $driverMock = Mockery::mock(); $driverMock->shouldReceive('scopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with(['disable_auto_auth' => 1])->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.tiktok.com/v2/auth/authorize?test=1', ])); From 3c3df4bc90b8e97077318ad1917951a239742a03 Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Tue, 8 Sep 2026 11:00:51 -0300 Subject: [PATCH 4/7] Remove unused docblock for scopes parameter in redirectToProvider method in SocialController. This change cleans up the code by eliminating unnecessary comments that no longer apply to the method's implementation. --- app/Http/Controllers/Auth/SocialController.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/Http/Controllers/Auth/SocialController.php b/app/Http/Controllers/Auth/SocialController.php index 204a14216..50554aa07 100644 --- a/app/Http/Controllers/Auth/SocialController.php +++ b/app/Http/Controllers/Auth/SocialController.php @@ -206,10 +206,6 @@ protected function filterConnectableIdentities( )->values()->all(); } - /** - * @param array $scopes - * @param array $parameters Extra query parameters for the provider's authorize URL. - */ protected function redirectToProvider(Request $request, string $driver, array $scopes, array $parameters = []): SymfonyResponse { $workspace = $request->user()->currentWorkspace; From d99c4cee70cba1280ac80bbac87746e9261aeeff Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Tue, 8 Sep 2026 11:12:40 -0300 Subject: [PATCH 5/7] Always forward the extra authorize parameters in redirectToProvider with() assigns $parameters rather than merging, and nothing else ever populates them, so with([]) is a no-op and the guard around it bought nothing. Dropping it restores the fluent chain the method had before. The Discord, Pinterest and X connect tests mock the driver whole, so they need the call stubbed even though the array stays empty. --- app/Http/Controllers/Auth/SocialController.php | 12 +++++------- tests/Feature/Social/DiscordControllerTest.php | 1 + tests/Feature/Social/PinterestControllerTest.php | 1 + tests/Feature/Social/XControllerTest.php | 1 + 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/app/Http/Controllers/Auth/SocialController.php b/app/Http/Controllers/Auth/SocialController.php index 50554aa07..89fc62b3f 100644 --- a/app/Http/Controllers/Auth/SocialController.php +++ b/app/Http/Controllers/Auth/SocialController.php @@ -212,14 +212,12 @@ protected function redirectToProvider(Request $request, string $driver, array $s $this->rememberConnectSession($request, $workspace); - $provider = Socialite::driver($driver)->scopes($scopes); - - if ($parameters !== []) { - $provider->with($parameters); - } - return Inertia::location( - $provider->redirect()->getTargetUrl() + Socialite::driver($driver) + ->scopes($scopes) + ->with($parameters) + ->redirect() + ->getTargetUrl() ); } diff --git a/tests/Feature/Social/DiscordControllerTest.php b/tests/Feature/Social/DiscordControllerTest.php index 7d9593c96..4dd0a3fd6 100644 --- a/tests/Feature/Social/DiscordControllerTest.php +++ b/tests/Feature/Social/DiscordControllerTest.php @@ -22,6 +22,7 @@ test('discord connect redirects to the oauth provider', function () { $driverMock = Mockery::mock(); $driverMock->shouldReceive('scopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with([])->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://discord.com/api/oauth2/authorize?test=1', ])); diff --git a/tests/Feature/Social/PinterestControllerTest.php b/tests/Feature/Social/PinterestControllerTest.php index 60e0572fd..7d40926e7 100644 --- a/tests/Feature/Social/PinterestControllerTest.php +++ b/tests/Feature/Social/PinterestControllerTest.php @@ -22,6 +22,7 @@ test('pinterest connect redirects to oauth provider', function () { $driverMock = Mockery::mock(); $driverMock->shouldReceive('scopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with([])->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://www.pinterest.com/oauth?test=1', ])); diff --git a/tests/Feature/Social/XControllerTest.php b/tests/Feature/Social/XControllerTest.php index 80fd09226..2c46fd224 100644 --- a/tests/Feature/Social/XControllerTest.php +++ b/tests/Feature/Social/XControllerTest.php @@ -22,6 +22,7 @@ test('x connect redirects to oauth provider', function () { $driverMock = Mockery::mock(); $driverMock->shouldReceive('scopes')->andReturnSelf(); + $driverMock->shouldReceive('with')->with([])->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://twitter.com/i/oauth2/authorize?test=1', ])); From 9d5341c87df94fce60003f63305855d97ebad46f Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Tue, 8 Sep 2026 11:12:40 -0300 Subject: [PATCH 6/7] Let YouTube reach a second Google account with select_account prompt=consent reopens the consent screen but never the account chooser, so a browser holding one Google session authorizes that account every time. channels?mine=true is scoped to whichever identity minted the token, so a Brand Account channel under a different Google account is absent from the response rather than merely unpicked, and the callback connects channels[0] regardless. Google documents prompt as a space-delimited list, and select_account and consent are distinct values, so the two compose. The connect test stubbed with() without constraining its argument, which left every redirect parameter unasserted; it now pins the whole array. --- app/Http/Controllers/Auth/YouTubeController.php | 2 +- tests/Feature/Social/YouTubeControllerTest.php | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Auth/YouTubeController.php b/app/Http/Controllers/Auth/YouTubeController.php index 13a779541..2fcb1ed2f 100644 --- a/app/Http/Controllers/Auth/YouTubeController.php +++ b/app/Http/Controllers/Auth/YouTubeController.php @@ -119,7 +119,7 @@ private function redirectToGoogle(): Response ->scopes($this->scopes) ->with([ 'access_type' => 'offline', - 'prompt' => 'consent', + 'prompt' => 'select_account consent', 'include_granted_scopes' => 'true', ]) ->redirect() diff --git a/tests/Feature/Social/YouTubeControllerTest.php b/tests/Feature/Social/YouTubeControllerTest.php index 0e7768b32..456ff201c 100644 --- a/tests/Feature/Social/YouTubeControllerTest.php +++ b/tests/Feature/Social/YouTubeControllerTest.php @@ -24,7 +24,11 @@ test('youtube connect redirects to oauth provider', function () { $driverMock = Mockery::mock(); $driverMock->shouldReceive('scopes')->andReturnSelf(); - $driverMock->shouldReceive('with')->andReturnSelf(); + $driverMock->shouldReceive('with')->with([ + 'access_type' => 'offline', + 'prompt' => 'select_account consent', + 'include_granted_scopes' => 'true', + ])->once()->andReturnSelf(); $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ 'getTargetUrl' => 'https://accounts.google.com/o/oauth2/v2/auth?test=1', ])); From 8201a8528f8248da254aac6c6c17c1805c1a6c5a Mon Sep 17 00:00:00 2001 From: Paulo Castellano Date: Tue, 8 Sep 2026 11:12:40 -0300 Subject: [PATCH 7/7] Force Instagram to re-authenticate so a second account is reachable Instagram reuses the browser session on a repeat connect, so a user logged in as one account cannot reach another; the callback answers wrong_account with no way forward. Business Login documents force_reauth for exactly this, against www.instagram.com/oauth/authorize, which is the host this provider already targets. The parameter goes in the provider rather than through with(), because getAuthUrl() builds the query by hand and never merges $parameters. The new test drives the real provider through the connect route instead of mocking Socialite, since the URL is assembled below the controller. --- app/Socialite/InstagramProvider.php | 1 + tests/Feature/Social/InstagramControllerTest.php | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/app/Socialite/InstagramProvider.php b/app/Socialite/InstagramProvider.php index 93c401ed1..faace2ed5 100644 --- a/app/Socialite/InstagramProvider.php +++ b/app/Socialite/InstagramProvider.php @@ -27,6 +27,7 @@ protected function getAuthUrl($state): string 'response_type' => 'code', 'scope' => implode(',', $this->getScopes()), 'state' => $state, + 'force_reauth' => 'true', ]); } diff --git a/tests/Feature/Social/InstagramControllerTest.php b/tests/Feature/Social/InstagramControllerTest.php index 3aee79f0f..a2a6d48b2 100644 --- a/tests/Feature/Social/InstagramControllerTest.php +++ b/tests/Feature/Social/InstagramControllerTest.php @@ -21,6 +21,14 @@ $this->workspace->members()->attach($this->user->id, ['role' => Role::Member->value]); }); +test('instagram authorize url forces reauth so a second account is reachable', function () { + $response = $this->actingAs($this->user)->get(route('app.social.instagram.connect')); + + expect($response->headers->get('Location')) + ->toStartWith('https://www.instagram.com/oauth/authorize') + ->toContain('force_reauth=true'); +}); + test('instagram connect redirects to oauth provider', function () { $driverMock = Mockery::mock(); $driverMock->shouldReceive('scopes')->andReturnSelf(); @@ -32,6 +40,8 @@ ->with('instagram') ->andReturn($driverMock); + $this->withoutExceptionHandling(); + $response = $this->actingAs($this->user) ->withHeader('X-Inertia', 'true') ->get(route('app.social.instagram.connect'));