From 21bbe96d6bae2d9557f8b8aa460419ce81f90ab8 Mon Sep 17 00:00:00 2001 From: Falconiere Barbosa Date: Wed, 10 Jun 2026 14:54:47 -0300 Subject: [PATCH] refactor(linkedin): move OAuth scopes into config/trypost.php platforms Consolidate the default scope set alongside the existing LinkedIn host config under config/trypost.php -> platforms.linkedin, matching the project convention that per-platform service config lives there. The default still drops the deprecated r_basicprofile scope, and LINKEDIN_EXTRA_SCOPES stays additive (merged onto the defaults rather than replacing them) so operators can opt back into legacy scopes without risking a misconfigured full-replacement. - config/trypost.php: add scopes + extra_scopes to platforms.linkedin - config/services.php: drop the moved extra_scopes key - LinkedInController::resolveScopes(): read both from trypost config - tests: repoint config() overrides to the new key --- .../Controllers/Auth/LinkedInController.php | 28 +++++++++---------- config/services.php | 6 ---- config/trypost.php | 12 ++++++++ .../Feature/Social/LinkedInControllerTest.php | 4 +-- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/app/Http/Controllers/Auth/LinkedInController.php b/app/Http/Controllers/Auth/LinkedInController.php index c619d210..2a4b0d5e 100644 --- a/app/Http/Controllers/Auth/LinkedInController.php +++ b/app/Http/Controllers/Auth/LinkedInController.php @@ -22,13 +22,6 @@ class LinkedInController extends SocialController protected SocialPlatform $platform = SocialPlatform::LinkedIn; - protected array $scopes = [ - 'openid', - 'profile', - 'email', - 'w_member_social', - ]; - public function connect(Request $request): Response|RedirectResponse { $this->ensurePlatformEnabled(); @@ -45,22 +38,29 @@ public function connect(Request $request): Response|RedirectResponse } /** - * Merge $this->scopes with any extra scopes the operator configured via - * `LINKEDIN_EXTRA_SCOPES` — comma-separated, e.g. `r_basicprofile`. Useful - * when the connected LinkedIn dev app has legacy or enterprise products - * not covered by the default Sign-In + Share-on-LinkedIn pair. + * Merge the default LinkedIn scopes with any extra scopes the operator + * configured via `LINKEDIN_EXTRA_SCOPES` — comma-separated, e.g. + * `r_basicprofile`. Useful when the connected LinkedIn dev app has legacy + * or enterprise products not covered by the default Sign-In + + * Share-on-LinkedIn pair. Both live under + * `config/trypost.php` → `platforms.linkedin`. + * + * @return array */ protected function resolveScopes(): array { - $extra = (string) config('services.linkedin.extra_scopes', ''); + /** @var array $scopes */ + $scopes = config('trypost.platforms.linkedin.scopes', []); + + $extra = (string) config('trypost.platforms.linkedin.extra_scopes', ''); if ($extra === '') { - return $this->scopes; + return $scopes; } $extraScopes = array_filter(array_map('trim', explode(',', $extra))); - return array_values(array_unique([...$this->scopes, ...$extraScopes])); + return array_values(array_unique([...$scopes, ...$extraScopes])); } public function callback(Request $request): View diff --git a/config/services.php b/config/services.php index f920d9ed..b6c194cc 100644 --- a/config/services.php +++ b/config/services.php @@ -41,12 +41,6 @@ 'client_id' => env('LINKEDIN_CLIENT_ID'), 'client_secret' => env('LINKEDIN_CLIENT_SECRET'), 'redirect' => env('LINKEDIN_CLIENT_REDIRECT'), - // Comma-separated list of OAuth scopes to request beyond the defaults - // (openid, profile, email, w_member_social). Useful for apps with - // legacy or enterprise products approved — e.g. set - // `LINKEDIN_EXTRA_SCOPES=r_basicprofile` to re-enable vanityName - // lookup via /v2/me. - 'extra_scopes' => env('LINKEDIN_EXTRA_SCOPES'), ], 'linkedin-openid' => [ diff --git a/config/trypost.php b/config/trypost.php index 0b1788ae..39882455 100644 --- a/config/trypost.php +++ b/config/trypost.php @@ -80,6 +80,18 @@ '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'), + // Default OAuth scopes requested on /connect/linkedin. Covers the + // two products auto-approved for new apps: Sign In with LinkedIn + // (openid, profile, email) + Share on LinkedIn (w_member_social). + // `r_basicprofile` is intentionally omitted — it's a 2018-deprecated + // legacy scope that new apps can't grant, and requesting it makes + // LinkedIn reject the whole authorize request. + 'scopes' => ['openid', 'profile', 'email', 'w_member_social'], + // Comma-separated extra scopes merged onto the defaults above, for + // apps with legacy/enterprise products approved — e.g. + // `LINKEDIN_EXTRA_SCOPES=r_basicprofile` to re-enable the vanityName + // lookup via /v2/me. + 'extra_scopes' => env('LINKEDIN_EXTRA_SCOPES'), ], 'linkedin-page' => [ 'enabled' => env('LINKEDIN_PAGE_ENABLED', true), diff --git a/tests/Feature/Social/LinkedInControllerTest.php b/tests/Feature/Social/LinkedInControllerTest.php index 43fc5cf4..768a9f01 100644 --- a/tests/Feature/Social/LinkedInControllerTest.php +++ b/tests/Feature/Social/LinkedInControllerTest.php @@ -40,7 +40,7 @@ }); test('linkedin connect requests the default scope set when LINKEDIN_EXTRA_SCOPES is unset', function () { - config(['services.linkedin.extra_scopes' => null]); + config(['trypost.platforms.linkedin.extra_scopes' => null]); $captured = []; @@ -72,7 +72,7 @@ test('linkedin connect appends LINKEDIN_EXTRA_SCOPES to the default scope set', function () { // Backward-compatibility: ops who have legacy products approved on // their LinkedIn app (e.g. r_basicprofile) opt back in via env. - config(['services.linkedin.extra_scopes' => 'r_basicprofile, r_emailaddress']); + config(['trypost.platforms.linkedin.extra_scopes' => 'r_basicprofile, r_emailaddress']); $captured = [];