Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Linkedin Laravel Package

linkedinapi/linkedin

A Laravel package that wraps the LinkedIn API, simplifying OAuth authentication and common endpoints for user profiles, connections, and sharing updates. It helps PHP developers quickly add LinkedIn login and social posting features to their applications.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and inspect the package

composer require linkedinapi/linkedin

The package ships a single LinkedIn class (historically LinkedIn.php / linkedin.php) rather than a Laravel package. Check vendor/linkedinapi/linkedin/ immediately after install to confirm:

  • the class name and file path,
  • whether it is PSR-4 autoloaded or requires a manual require_once,
  • which config constants or constructor args it expects (API_KEY, API_SECRET, OAUTH_CALLBACK, OAUTH_TOKEN, OAUTH_TOKEN_SECRET).

2. Get credentials

Create a LinkedIn app in the LinkedIn Developer Portal. Note the app's client ID/secret and register your callback URL (https://your-app.test/auth/linkedin/callback). Be aware that most useful scopes (r_liteprofile, r_emailaddress, w_member_social) now require OAuth 2.0 and, for some, LinkedIn partner approval — this SDK targets the legacy OAuth 1.0a/v1 API.

3. Bind it in Laravel

Create a small service provider so you never new LinkedIn() in controllers:

// app/Providers/LinkedInServiceProvider.php
public function register(): void
{
    $this->app->singleton(\LinkedIn::class, fn () => new \LinkedIn(
        config('services.linkedin.key'),
        config('services.linkedin.secret'),
        config('services.linkedin.callback'),
    ));
}

Add credentials to config/services.php and .env:

'linkedin' => [
    'key' => env('LINKEDIN_KEY'),
    'secret' => env('LINKEDIN_SECRET'),
    'callback' => env('LINKEDIN_CALLBACK'),
],

4. First use case — "Sign in with LinkedIn" and fetch the profile

Wire two routes: one that obtains a request token and redirects to LinkedIn, and one callback that exchanges the verifier for an access token and calls fetch('GET', '/v1/people/~:(id,first-name,last-name,email-address)'). Persist the returned token pair against your users row, then redirect into your app.

If your goal is simply social login in 2024+, stop here and evaluate laravel/socialite + socialiteproviders/linkedin instead; this package will not work against LinkedIn's current OAuth 2.0 endpoints without modification.

Implementation Patterns

Thin wrapper service. Never let the SDK leak into controllers or models. Wrap it:

class LinkedInClient
{
    public function __construct(private \LinkedIn $sdk) {}

    public function profile(string $token, string $secret): array
    {
        $this->sdk->setTokenAccess($token, $secret);

        return $this->sdk->fetch('GET', '/v1/people/~:(id,first-name,last-name,email-address)', ['format' => 'json']);
    }
}

This gives you one place to swap in a Guzzle/Http-based OAuth 2.0 implementation later.

OAuth handshake as controller actions.

Route::get('/auth/linkedin', [LinkedInAuthController::class, 'redirect']);
Route::get('/auth/linkedin/callback', [LinkedInAuthController::class, 'callback']);

public function redirect(LinkedInClient $client)
{
    $token = $client->requestToken();          // getRequestToken()
    session(['linkedin_request_token' => $token]);

    return redirect($client->authorizeUrl($token)); // redirect()
}

public function callback(Request $request, LinkedInClient $client)
{
    $access = $client->exchange(
        session()->pull('linkedin_request_token'),
        $request->query('oauth_verifier')       // retrieveTokenAccess()
    );

    auth()->user()->update([
        'linkedin_token' => encrypt($access['token']),
        'linkedin_secret' => encrypt($access['secret']),
    ]);

    return redirect()->route('dashboard');
}

Keep the request token in the session (or a short-lived cache entry) so concurrent logins don't collide.

Token storage and retrieval. Store OAuth tokens encrypted (encrypt() cast or a EncryptedString cast). Add a small accessor on the User model that decrypts and hands the pair to your LinkedInClient. Never log tokens; redact oauth_token/oauth_token_secret from request logs.

Queued API calls. LinkedIn calls are slow and rate-limited. Push outbound work (sharing a post, syncing profile fields) onto a queue:

dispatch(new PublishLinkedInPost($user, $payload));

In the job, resolve LinkedInClient from the container, catch SDK exceptions, and use $this->release(60 * 5) on rate-limit responses rather than failing.

Testing. Because the SDK is a concrete class, bind a fake in tests:

$this->mock(LinkedInClient::class, function ($mock) {
    $mock->shouldReceive('profile')->andReturn(['id' => 'abc', 'firstName' => 'Ada']);
});

Avoid hitting LinkedIn in CI; record fixtures of real fetch() responses and replay them.

Integration tips.

  • Register a LinkedIn facade only if you really need LinkedIn::fetch() syntactically — otherwise inject the client.
  • Use a dedicated middleware or policy check before any write action; LinkedIn scopes are per-token and per-app.
  • Cache profile reads for a few minutes (Cache::remember) since the legacy API is slow and rate-limited.

Gotchas and Tips

The API is effectively dead. This SDK was built for LinkedIn's v1 REST API and OAuth 1.0a. LinkedIn sunset v1 around 2019 and requires OAuth 2.0 with OpenID Connect for profile data. Expect 401, 403, or 410 responses for /v1/people/~ and related endpoints. Treat this package as a legacy integration or a learning reference, not a greenfield choice.

Autoloading and naming. The package predates PSR-4. You may get a global LinkedIn class (\LinkedIn) that collides with nothing in Laravel but is not discoverable by Composer's classmap in all setups. If class_exists(\LinkedIn::class) fails, add a require_once in your service provider or a classmap entry in composer.json, then composer dump-autoload.

Config quirks. Many forks read constants (API_KEY, API_SECRET) defined at include time rather than constructor args. In Laravel this is painful because config:cache runs in a separate process. Prefer the constructor-based variant; if unavailable, define() the constants in a service provider before resolving the class — and never rely on .env being readable at runtime.

Error handling is weak. The SDK often returns false or an XML/JSON error body instead of throwing. Wrap every call and normalize:

$result = $client->fetch('GET', $endpoint);
if ($result === false || isset($result['errorCode'])) {
    throw new LinkedInException($result['message'] ?? 'Unknown LinkedIn error');
}

Log the raw body (with tokens stripped) at debug level.

Redirect and callback URLs must match exactly. LinkedIn is strict about the registered callback, including trailing slashes and scheme. Use route('linkedin.callback') rather than a hardcoded string, and ensure APP_URL is correct behind proxies (TrustProxies).

Token longevity. OAuth 1.0a tokens are long-lived but revocable; OAuth 2.0 tokens expire in ~60 days. If you migrate, add a refresh job. Handle 401 by clearing stored tokens and prompting re-auth rather than retrying endlessly.

Rate limits and payload sizes. Legacy LinkedIn enforced per-app and per-user throttles. Batch profile fields into one :(...) projection instead of multiple calls, and back off exponentially on 429.

Extension points. Subclass LinkedIn and override the HTTP request method to route through Laravel's Http client — this gives you retries, timeouts, and logging without forking. For a forward path, replace the SDK entirely: Socialite for the handshake, then Http::withToken($token)->get('https://api.linkedin.com/v2/me') for data. That is the pattern most Laravel teams should actually ship.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle