truckersmp/steam-socialite
A Laravel Socialite provider for Steam authentication. Let users sign in with Steam and retrieve their Steam profile data using a familiar Socialite driver, making it easy to add Steam login to Laravel apps and community platforms.
truckersmp/steam-socialite is a Socialite driver that authenticates users via Steam OpenID and returns their SteamID64 plus public profile data. Day-to-day, it is the "Log in with Steam" button on a community/gaming site.
Minimum setup (first use case: Steam login):
composer require truckersmp/steam-socialite — pin ^1.10 (see Gotchas; anything below 1.10.0 has a known account-takeover advisory).boot() or a SocialiteWasCalled listener):
Socialite::extend('steam', fn ($app) => $app->make(
\TruckersMP\SteamSocialite\SteamProvider::class
));
config/services.php:
'steam' => [
'client_id' => env('STEAM_CLIENT_ID'), // your Steam Web API key
'client_secret' => env('STEAM_CLIENT_SECRET'),
'redirect' => env('STEAM_REDIRECT_URI'), // absolute, exact URL
],
GET /auth/steam/redirect → Socialite::driver('steam')->redirect(), and GET /auth/steam/callback → Socialite::driver('steam')->user().web middleware group (sessions required since v1.10.0).Where to look first: the security advisory GHSA-cfcr-wjg4-3vx9 and the v1.10.0 diff — the session-state and callback-URL rules change how you wire routes. Then the provider's redirectUrl/getUserByToken methods to confirm how the SteamID64 is parsed.
Standard session-backed flow (recommended):
// redirect
return Socialite::driver('steam')->redirect();
// callback
try {
$steam = Socialite::driver('steam')->user();
} catch (\Laravel\Socialite\Two\InvalidStateException $e) {
return redirect()->route('login')->withErrors('Steam login expired, try again.');
}
$user = User::firstOrCreate(
['steam_id' => $steam->getId()], // SteamID64
['name' => $steam->getNickname(), 'avatar' => $steam->getAvatar()]
);
Auth::login($user);
Account linking (existing logged-in user attaches Steam): same flow, but in the callback do $request->user()->update(['steam_id' => $steam->getId()]) instead of logging in, and guard against a steam_id already owned by someone else. Consider stashing the intent (link vs login) in the session before redirect, since v1.10.0 already requires sessions.
Stateless / SPA / API-driven flows: call stateless() on both legs — ->stateless()->redirect() and ->stateless()->user(). This disables the built-in CSRF state, so pair it with your own signed nonce or a short-lived signed callback URL; otherwise the v1.10.0 hardening buys you nothing.
Behind a proxy / load balancer: configure TrustProxies ($proxies = '*' or your LB IPs) so Laravel generates the same scheme+host the browser sees. Because the callback must match the redirect URL exactly, mismatches surface as rejected logins, not obvious config errors. Set APP_URL to the real HTTPS host and consider URL::forceScheme('https').
Controller/service structure: wrap Socialite::driver('steam')->user() in a small SteamAuthService so you can swap in a fake in tests and centralize try/catch and user provisioning. Keep the callback controller thin.
Testing: fake Socialite (Socialite::shouldReceive('driver->user')->andReturn($fakeUser)) for provisioning tests, and add one integration-ish test per environment (proxy on/off) asserting your redirect URI matches what the callback sees.
Socialite::driver('steam')->redirect()->getTargetUrl() and $request->fullUrl() side by side.api route group (no StartSession), you'll get InvalidStateException every time — either move it to web or go stateless() on both legs.stateless() must be on both calls. Setting it only on the callback (or only on redirect) produces state mismatches that look like random failures.https://steamcommunity.com/openid/id/<17-digit SteamID64>. Hand-rolled mocks, fixtures, or self-hosted OpenID stubs that return variants will now fail — update test doubles.TrustProxies, APP_URL, and any CDN that rewrites Host/X-Forwarded-* headers before touching package code.getUserByToken / mapUserToObject, or register under a custom driver name via Socialite::extend if you run multiple Steam app configurations (e.g. per-tenant).InvalidStateException is nearly always one of three things — missing session middleware, mismatched callback URL, or stateless() applied inconsistently. Log all three inputs before escalating.How can I help you explore Laravel packages today?