-
-
Notifications
You must be signed in to change notification settings - Fork 58
fix(linkedin): drop deprecated r_basicprofile from default scopes #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
410eb96
03a3d9e
4987a31
21bbe96
8e164bd
a2a7f44
8b8b59f
2b75820
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,16 +24,6 @@ class LinkedInPageController extends SocialController | |
|
|
||
| protected SocialPlatform $platform = SocialPlatform::LinkedInPage; | ||
|
|
||
| protected array $scopes = [ | ||
| 'openid', | ||
| 'profile', | ||
| 'email', | ||
| 'w_organization_social', | ||
| 'r_organization_social', | ||
| 'rw_organization_admin', | ||
| 'w_member_social', | ||
| ]; | ||
|
|
||
| public function connect(Request $request): SymfonyResponse|RedirectResponse | ||
| { | ||
| $this->ensurePlatformEnabled(); | ||
|
|
@@ -55,7 +45,7 @@ public function connect(Request $request): SymfonyResponse|RedirectResponse | |
|
|
||
| return Inertia::location( | ||
| Socialite::driver($this->driver) | ||
| ->scopes($this->scopes) | ||
| ->scopes(config('trypost.platforms.linkedin-page.scopes')) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dropped the hardcoded |
||
| ->with([ | ||
| 'redirect_uri' => config('services.linkedin-openid.redirect_page'), | ||
| ]) | ||
|
|
@@ -80,7 +70,7 @@ public function callback(Request $request): View|RedirectResponse | |
|
|
||
| try { | ||
| $socialUser = Socialite::driver($this->driver) | ||
| ->scopes($this->scopes) | ||
| ->scopes(config('trypost.platforms.linkedin-page.scopes')) | ||
| ->with([ | ||
| 'redirect_uri' => config('services.linkedin-openid.redirect_page'), | ||
| ]) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,10 +80,14 @@ | |
| 'api' => env('LINKEDIN_API', 'https://api.linkedin.com'), | ||
| // OAuth host is different from the data API (api.linkedin.com). | ||
| 'oauth_api' => env('LINKEDIN_OAUTH_API', 'https://www.linkedin.com'), | ||
| // Scopes for LinkedIn authentication | ||
| 'scopes' => array_values(array_filter(array_map('trim', explode(',', (string) env('LINKEDIN_SCOPES', 'openid,profile,email,w_member_social'))))), | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personal connect scopes. Note this is full-replace, not additive: an operator who sets |
||
| ], | ||
| 'linkedin-page' => [ | ||
| 'enabled' => env('LINKEDIN_PAGE_ENABLED', true), | ||
| 'api' => env('LINKEDIN_PAGE_API', 'https://api.linkedin.com'), | ||
| // Scopes for LinkedIn Page authentication | ||
| 'scopes' => array_values(array_filter(array_map('trim', explode(',', (string) env('LINKEDIN_PAGE_SCOPES', 'openid,profile,email,w_organization_social,r_organization_social,rw_organization_admin,w_member_social'))))), | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Company Pages scopes — added per your request to cover both flows in this PR. Same explode pattern, overridable via |
||
| ], | ||
| 'x' => [ | ||
| 'enabled' => env('X_ENABLED', true), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,57 @@ | |
| expect(session('social_connect_workspace'))->toBe($this->workspace->id); | ||
| }); | ||
|
|
||
| /** | ||
| * Mock the LinkedIn Socialite driver, hit /connect, and return the scopes | ||
| * the controller requested. | ||
| * | ||
| * @return array<int, string> | ||
| */ | ||
| $captureConnectScopes = function (object $test): array { | ||
| $captured = []; | ||
|
|
||
| $driverMock = Mockery::mock(); | ||
| $driverMock->shouldReceive('scopes') | ||
| ->withArgs(function (array $scopes) use (&$captured) { | ||
| $captured = $scopes; | ||
|
|
||
| return true; | ||
| }) | ||
| ->andReturnSelf(); | ||
| $driverMock->shouldReceive('redirect')->andReturn(Mockery::mock([ | ||
| 'getTargetUrl' => 'https://www.linkedin.com/oauth/v2/authorization?test=1', | ||
| ])); | ||
|
|
||
| Socialite::shouldReceive('driver') | ||
| ->with('linkedin') | ||
| ->andReturn($driverMock); | ||
|
|
||
| $test->actingAs($test->user) | ||
| ->withHeader('X-Inertia', 'true') | ||
| ->get(route('app.social.linkedin.connect')); | ||
|
|
||
| return $captured; | ||
| }; | ||
|
|
||
| test('linkedin connect requests the default scope set', function () use ($captureConnectScopes) { | ||
| config(['trypost.platforms.linkedin.scopes' => ['openid', 'profile', 'email', 'w_member_social']]); | ||
|
|
||
| expect($captureConnectScopes($this))->toEqualCanonicalizing([ | ||
| 'openid', 'profile', 'email', 'w_member_social', | ||
| ]); | ||
| }); | ||
|
|
||
| test('linkedin connect requests the scopes configured via LINKEDIN_SCOPES', function () use ($captureConnectScopes) { | ||
| // Operators whose LinkedIn app has legacy/enterprise products approved | ||
| // override the default set via LINKEDIN_SCOPES (exploded into the config | ||
| // array), e.g. re-adding r_basicprofile to restore the vanityName lookup. | ||
| config(['trypost.platforms.linkedin.scopes' => ['openid', 'profile', 'email', 'w_member_social', 'r_basicprofile']]); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two connect tests drive scopes via |
||
|
|
||
| expect($captureConnectScopes($this))->toEqualCanonicalizing([ | ||
| 'openid', 'profile', 'email', 'w_member_social', 'r_basicprofile', | ||
| ]); | ||
| }); | ||
|
|
||
| test('linkedin oauth callback creates account', function () { | ||
| session([ | ||
| 'social_connect_workspace' => $this->workspace->id, | ||
|
|
@@ -99,7 +150,7 @@ | |
| // splits on space (the OAuth 2.0 default), so approvedScopes lands as | ||
| // a single-element array with the whole CSV inside. The save path | ||
| // must normalize back to individual tokens. | ||
| $socialiteUser->approvedScopes = ['email,openid,profile,r_basicprofile,w_member_social']; | ||
| $socialiteUser->approvedScopes = ['email,openid,profile,w_member_social']; | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updating the scope list in the fixture to match the new default — the CSV-normalization logic this test covers is unchanged. |
||
|
|
||
| Socialite::shouldReceive('driver') | ||
| ->with('linkedin') | ||
|
|
@@ -116,7 +167,7 @@ | |
|
|
||
| $account = SocialAccount::where('platform_user_id', 'abc123xyz')->first(); | ||
| expect($account->scopes)->toEqualCanonicalizing([ | ||
| 'email', 'openid', 'profile', 'r_basicprofile', 'w_member_social', | ||
| 'email', 'openid', 'profile', 'w_member_social', | ||
| ]); | ||
| }); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resolveScopes()is gone —connect()reads the resolved array straight from config. All scope logic (default + override) now lives inconfig/trypost.php, nothing to merge here.