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

Socialiteproviders Evopixel Laravel Package

evopixel/socialiteproviders-evopixel

EvoPixel provider for Laravel Socialite adds OAuth login support to Laravel apps. Install via Composer, configure EvoPixel credentials, and let users sign in with their EvoPixel account using the familiar Socialite API.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a SocialiteProviders driver (authorization code + S256 PKCE, optional OIDC) for a platform that also exposes roles, permissions and linked accounts. It plugs into the existing socialiteproviders/manager 4.x ecosystem rather than shipping its own auth stack, so the wiring is the familiar one: install, register the listener, add a services block, add a redirect/callback pair.

  1. Install the driver alongside the manager (the driver requires Manager 4.x):

    composer require socialiteproviders/manager:^4.0 socialiteproviders/<provider>:^1.0
    
  2. Register the provider by listening for the manager event in app/Providers/EventServiceProvider.php:

    protected $listen = [
        \SocialiteProviders\Manager\SocialiteWasCalled::class => [
            \SocialiteProviders\<Provider>\<Provider>ExtendSocialite::class.'@handle',
        ],
    ];
    
  3. Add credentials to config/services.php — the README is the single source of truth for the exact key names, but expect client_id, client_secret, redirect, and (for OIDC) a discovery/issuer URL plus a toggle for ID token validation:

    'platform' => [
        'client_id'     => env('PLATFORM_CLIENT_ID'),
        'client_secret' => env('PLATFORM_CLIENT_SECRET'),
        'redirect'      => env('PLATFORM_REDIRECT_URI'),
    ],
    
  4. Two routes and one controller. Nothing else is required to get a first login working:

    Route::get('/auth/redirect', fn () => Socialite::driver('platform')->redirect());
    Route::get('/auth/callback', [PlatformAuthController::class, 'callback']);
    

Where to look first: the README section describing the services array and the scopes for roles/permissions/linked accounts — those two things determine whether your first request even returns the data you expect. Read the OIDC subsection only if the README tells you the platform issues ID tokens you intend to trust.

First use case: a "Log in with platform" button that resolves a local user, then immediately reads roles off the returned user to decide which local role to grant. Because the driver already returns roles and permissions from the current session, you can do the mapping at callback time without a second API round trip.

Implementation Patterns

Callback controller — the canonical shape. Resolve the user, then persist the identity plus tokens in one transaction:

public function callback()
{
    $remote = Socialite::driver('platform')->user();

    $account = PlatformAccount::updateOrCreate(
        ['provider_id' => $remote->getId()],
        [
            'user_id'       => auth()->id() ?? User::fromEmail($remote->getEmail())->id,
            'nickname'      => $remote->getNickname(),
            'access_token'  => $remote->token,
            'refresh_token' => $remote->refreshToken,
            'expires_at'    => now()->addSeconds($remote->expiresIn ?? 3600),
            'roles'         => $remote->user['roles'] ?? [],
            'permissions'   => $remote->user['permissions'] ?? [],
        ]
    );

    return redirect()->intended('/dashboard');
}

Token storage. Treat refresh_token as a secret: an encrypted cast on the model, and never log the user() payload verbatim (it contains the token and, under OIDC, the raw ID token).

Refresh token rotation is the pattern that bites. Every refresh returns a new refresh token and invalidates the old one. Always persist the new value in the same operation that consumes the old one, guarded by a lock so two concurrent requests can't both rotate and strand the user:

$account = Cache::lock("platform-refresh:{$account->id}", 10)->block(5, function () use ($account) {
    if ($account->expires_at->isFuture()) {
        return $account; // someone else already refreshed
    }

    $fresh = Socialite::driver('platform')->refreshToken($account->refresh_token);

    $account->update([
        'access_token'  => $fresh->token,
        'refresh_token' => $fresh->refreshToken ?? $account->refresh_token,
        'expires_at'    => now()->addSeconds($fresh->expiresIn ?? 3600),
    ]);

    return $account;
});

Wrap this in a small PlatformClient service so your API calls always go through a token that is known fresh, rather than sprinkling refresh logic through controllers.

Role/permission sync. Two complementary workflows: sync at login (cheap, keeps the common case accurate), and a scheduled job for long-lived sessions where roles change server-side. Do not rely on the login snapshot alone for authorization decisions on a user who has been signed in for days.

Linked accounts. The driver exposes linked accounts on the returned payload. Use them for identity reconciliation — matching an existing local user by a verified linked account is more reliable than by email, and it's the natural hook for account-merging flows.

OIDC. If you enable it, prefer validating the signed ID token and treating its claims as the source of truth for identity (sub, nonce, aud), and let discovery + JWKS handle key rotation for you. If you only need profile data, leave OIDC off — it adds a discovery round trip and a nonce round trip to every login.

Central logout. Only official platform applications may call it, so it cannot be a general-purpose feature of your app. Pattern: local logout always, then a best-effort redirect to the platform's end-session endpoint only when the client is registered as an official application. Guard it with a config flag so a non-official deployment never attempts it.

Revocation on logout. On sign-out, revoke the token and null out the stored refresh token. If revocation fails (network, already-revoked), swallow the error and clear local state anyway — a stale token in your DB is worse than a failed revocation.

Testing. Fake the HTTP layer rather than mocking Socialite, so PKCE/state/nonce handling is exercised:

Http::fake([
    '*/oauth/token'    => Http::response(['access_token' => 'x', 'refresh_token' => 'y', 'expires_in' => 3600]),
    '*/userinfo'       => Http::response(['sub' => '123', 'roles' => ['admin']]),
]);

For the session-bound parts, remember the redirect and callback must run in the same test session; $this->get('/auth/redirect') followed by $this->get('/auth/callback') on the same test case does this correctly.

Gotchas and Tips

  • stateless() breaks this driver. State is session-bound and PKCE code verifiers plus the OIDC nonce live in the session. Calling ->stateless() on a stateless API endpoint will produce InvalidStateException or a token exchange failure. If you need mobile/API auth, this is the wrong tool — use a device-code or password grant separately.
  • Session affinity is now a deployment requirement. Behind a load balancer with a non-shared session store, the callback lands on a node that never saw the redirect and state validation fails intermittently. Fix the session driver (database/redis/cookie) before debugging the provider.
  • Failed refreshes are silent logouts. A single dropped rotation permanently invalidates the user's token. Log refresh failures with the account ID, and on invalid_grant mark the account as needing re-authentication rather than retrying in a loop.
  • Discovery and JWKS need caching. Discovery adds a network call to the login path and JWKS fetches happen on ID token validation. Cache both (the package/README documents the cache keys); an outage of the discovery endpoint otherwise takes your login down with it.
  • Clock skew on ID token validation. Allow a small leeway for exp/iat/nbf; containers with drifting clocks will otherwise reject valid tokens at random.
  • redirect must match exactly. Register the full absolute callback URL in the platform application, including scheme and trailing slash. This is the single most common cause of a first-integration failure.
  • Scopes for roles/permissions/linked accounts may need approval. If the payload comes back without them, check scopes before assuming a driver bug.
  • Central logout is gated to official platform applications. Attempting it from a third-party client registration will be rejected. Feature-flag it, and always perform local logout first so a rejected call can't leave the session alive.
  • PHP 7.4 support shapes the code you'll write around it. No enums, readonly properties, or constructor promotion if the package's own constraints force you to stay 7.4-compatible in shared DTOs. Tested on 7.4 and 8.2 — if you're on 8.3+, run your own smoke test against the auth flow before shipping.
  • Manager 4.x only. If your app is pinned to socialiteproviders/manager 3.x, you'll get a dependency conflict; the registration mechanism differs between majors.
  • Extension points: subclass the provider and override getUserByToken()/mapUserToObject() when the platform adds claims the driver doesn't map yet, and use ->with(['prompt' => 'consent']) for flow parameters rather than editing the package. Report genuinely missing claims upstream instead of forking — the README is the only integration doc, so a fork will drift.
  • Debugging checklist when login fails: confirm the listener is in EventServiceProvider (a missing listener gives a confusing "Driver [platform] is not supported"), confirm config/services.php keys match the README exactly, confirm config:clear after env changes, then inspect the actual token-endpoint response body with HTTP logging enabled — the driver surfaces little of it in the exception message.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource