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
This commit is contained in:
Falconiere Barbosa 2026-06-10 14:54:47 -03:00
parent 4987a31e8a
commit 21bbe96d6b
No known key found for this signature in database
GPG key ID: A25861196368D204
4 changed files with 28 additions and 22 deletions

View file

@ -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<int, string>
*/
protected function resolveScopes(): array
{
$extra = (string) config('services.linkedin.extra_scopes', '');
/** @var array<int, string> $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

View file

@ -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' => [

View file

@ -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),

View file

@ -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 = [];