league/oauth2-linkedin
A LinkedIn OAuth 2.0 provider for the League OAuth2 Client. It handles LinkedIn authorization redirects, access token exchange, and resource owner details, making LinkedIn login integration simple in PHP applications.
Architecture fit. league/oauth2-linkedin is a thin provider adapter — a single class extending League\OAuth2\Client\Provider\AbstractProvider plus a resource-owner value object. It carries no runtime dependencies beyond league/oauth2-client, no framework coupling, no service container registration, no facades. For a Laravel codebase it is pure library code that you would wrap in your own service class or Socialite driver. The architectural surface area is negligible: five overridden methods (getBaseAuthorizationUrl, getBaseAccessTokenUrl, getResourceOwnerDetailsUrl, getDefaultScopes, createResourceOwner) and a handful of accessors. Practically, this is not a system you integrate; it is a system you copy.
Integration feasibility. Straightforward mechanically, but likely infeasible in production on the merits. The package's defaults target LinkedIn's legacy v2 surface: scopes r_liteprofile and r_emailaddress, and resource-owner retrieval against /v2/me with a follow-up call to /v2/emailAddress. LinkedIn's "Sign In with LinkedIn" products were superseded by Sign In with LinkedIn using OpenID Connect, which requires the standard openid profile email scopes and a GET /v2/userinfo call returning an OIDC-shaped payload. New LinkedIn applications cannot request the legacy products, so out of the box this provider will fail at the authorization step, not at the code step. Feasibility therefore hinges on how much of the class you are willing to override — at which point you are writing a new provider and using this repo only as a template.
Technical risk.
firstName, lastName, headline, pictureUrls). OIDC's userinfo returns given_name, family_name, picture, sub, email_verified. Any mapping layer above this will need rework regardless.league/oauth2-client directly), but it does mean you cannot lean on a large installed base or downstream patch traffic as a safety net.Key questions.
sub, name, email, picture), or do we need LinkedIn organization/learning products that require separate API access anyway?Stack fit. Laravel already has an OAuth answer in Socialite; for a single provider, adding league/oauth2-client plus this provider duplicates the abstraction. The cleanest fit is to use Socialite's LinkedIn driver for the authorization-code dance, or — if Socialite is unavailable or undesirable — to fork this provider into app/Support/OAuth/LinkedInProvider.php and register it through a small Socialite::extend() call or a dedicated LinkedInClient service. Treat the repo as reference source, not as an installed dependency.
Migration path. If the dependency is already present, the migration is a replacement, not an upgrade:
getFirstName, getEmail, getImageUrl, etc.) and map each to an OIDC claim.LinkedInIdentity DTO with neutral fields (subject, email, emailVerified, givenName, familyName, pictureUrl). All application code moves to this DTO before any provider swap.league/oauth2-linkedin dependency and its lockfile entry once the last call site is migrated.Compatibility. PHP version support should be verified against your runtime (the 2020 code was written for PHP 7.x; it will almost certainly run on 8.x, but no one has certified it). league/oauth2-client major-version drift is the real concern — the provider pins an old constraint, so Composer may force a downgrade of the client library across the whole application, which is a much wider blast radius than the LinkedIn integration itself. Check composer why league/oauth2-client before touching anything.
Sequencing.
LinkedInIdentity DTO and migrate call sites behind it (no behavior change).Maintenance. Assume zero upstream maintenance. The realistic maintenance unit is "one internal owner, a few hours per year" — provided the code is forked and small. Leaving it as an external dependency is worse operationally than forking, because you cannot patch a stale default scope without either a Composer patch plugin, a repositories override, or a wait that will never end. Budget for the fork explicitly.
Support. No vendor, no SLA, no security response channel beyond GitHub issues on a dormant repo. Escalation path is "read the source," which is viable here only because the class is ~200 lines. Document that the fork owner is a named engineer, not "the team."
Scaling. Auth volume is the wrong thing to worry about — LinkedIn OAuth is a low-QPS, user-initiated flow. The scaling concern is LinkedIn's rate limits and the extra round trip the legacy resource-owner logic performs (a second API call to fetch the email address). The OIDC userinfo endpoint returns identity and email in one call, so the migration is a net latency and quota win. Cache the resulting profile locally keyed on sub so re-logins do not require a fresh API call.
Failure modes.
invalid_scope error at the redirect. Detectable only at runtime; requires a smoke test in CI against a real LinkedIn app, not a mock.email empty because the claim name changed from emailAddress to email. Enforce a non-null invariant on LinkedInIdentity::email at construction.league/oauth2-client breaking an unrelated integration. Mitigate with composer why before install, and pin.Ramp-up. Low for any Laravel engineer familiar with OAuth: the class is small and idiomatic, and Socialite/League patterns are widely understood. The real ramp-up cost is LinkedIn-side, not code-side — app verification, product access requests, redirect URI registration, and understanding which scopes your app is actually entitled to. That work is measured in days of calendar time and is the same regardless of which library you pick, which is precisely why the library choice should not be the long pole. Recommendation: do not adopt as a dependency; use as a reference implementation, ship an OIDC-correct provider behind your own DTO, and revisit only if the upstream repo publishes an OpenID Connect release.
How can I help you explore Laravel packages today?