sirwaddles/steamauth
SteamAuth is a Laravel package that adds Steam OpenID authentication to your app. It handles Steam login redirects, validates OpenID responses, and retrieves the authenticated user's Steam profile data for easy account linking.
Confirm your framework before you install anything. Despite the "Laravel/PHP" listing, sirwaddles/steamauth is a Symfony bundle (SteamAuthBundle). It ships no ServiceProvider, no facade, no Auth driver, no publishable config. In a Laravel app, composer require is the wrong first move — open the repo, find the OpenID verification routine, and copy it into a SteamService you own. It's MIT; porting is legitimate and cheaper than mounting a Symfony bundle inside Illuminate's container. Reimplementing the flow is realistically 100–150 lines including routes and tests.
If you're actually on Symfony (2/3 era):
composer require sirwaddles/steamauth — verify the exact package name against the repo (SteamAuthBundle) before you commit to it in a lockfile.AppKernel.php (or config/bundles.php on Symfony 3.4+/4).return_url and realm in config.yml — absolute HTTPS URLs, no trailing slash drift between the two.First use case — the whole thing, end to end: a "Sign in through Steam" button → redirect to https://steamcommunity.com/openid/login with openid.mode=checkid_setup → handle the callback → re-submit the returned openid.* params with openid.mode=check_authentication → require is_valid:true → extract the SteamID64 from openid.claimed_id → look up or create the user → log in. That's the entire product surface. Everything else is user model and session wiring on your side.
Smoke test before anything else: hit the redirect URL manually in a browser against a real Steam account and confirm the callback lands with a full set of openid.* parameters. If the bundle's era doesn't match your Symfony version, this is where you'll find out — the redirect fires but the callback handler 500s on container wiring.
OpenID 2.0, not OAuth. Steam does not offer OAuth/OIDC for login. The pattern is fixed: redirect out with checkid_setup, then on return POST the parameters back to Steam with check_authentication and validate is_valid:true. There is no token exchange, no refresh, no scopes, no userinfo endpoint. If you're expecting Socialite-shaped flows, reset your mental model.
Link-on-first-login is the canonical model. Add a nullable unique steam_id (string, 17 digits) to users. On callback: extract the SteamID64, firstOrCreate the user, log them in. Decide early whether Steam is a primary or secondary identity — the assessment sources are right that this is the single biggest product decision the integration forces, and it changes the schema (one user → many identities) more than the auth code.
Extract the ID with a strict regex; don't trust the URL. Match openid.claimed_id against #^https?://steamcommunity\.com/openid/id/(\d{17})$#. Anything that doesn't match exactly is an error, not a warning. Loose matching here is an account-takeover vector.
Enrich after auth. This bundle authenticates; it does not fetch profile, inventory, or bans. Follow with a Steam Web API call (ISteamUser/GetPlayerSummaries/v2, API key required) as a separate service. Budget that as separate work — it's the most common scoping mistake with this package.
Config-driven endpoints. Whatever you build (or port), keep the Steam OpenID URLs in config, not literals. OpenID 2.0 is a deprecated protocol; if Valve sunsets or repoints it, a config change is a deploy, a code change is an emergency.
Behind a feature flag with a non-Steam fallback. Steam OpenID outages are real and happen. If Steam is the only login path and steamcommunity.com is down, you have a total-lockout incident, not a degraded-experience incident. Keep email/password or another provider live during rollout.
Sequence your spike. Day 1: stand up the redirect + callback against a test Steam account in isolation. Day 2: implement the same flow via socialiteproviders/steam as a baseline comparison. Pick on that evidence. Treat the bundle as a reference implementation for the handshake order and the parameter names, and let the comparison decide which one ships.
The 0.60 score and 10 stars are the signal, not the packaging. Zero dependents means zero production validation for the highest-blast-radius code path in your app. Any adoption is a fork in practice — you inherit the code, the security review, and the dependency pinning. Price it that way in your estimate.
Composer will fight you if you try to install it transitively into Laravel. The bundle's Symfony component pins will almost certainly conflict with the Symfony components Illuminate already requires. If you must reuse the code, vendor the extracted classes into app/ or a private package — do not add the bundle to your dependency graph just to get at 60 lines of OpenID logic.
Protocol sunset is a standing risk, not a one-time one. OpenID 2.0 is deprecated and Valve has not announced an OAuth2 replacement. Track it. Keep the endpoint config-driven (see above) so a Valve-side change is a config deploy.
Assertion validation is the release gate. Do a dedicated security pass on: signature verification, return_to/realm binding, replay protection, and session fixation on the post-callback login. If you're porting the code, verify each of these is present — it's the reason to read the source rather than paste it.
Callback URL discipline. return_url, realm, the button's target, and the registered config all have to agree exactly — scheme, host, path, trailing slash. A single character of drift and OpenID returns is_valid:false with no useful error message. Log the full openid.* payload on callback failure; Steam's error responses are opaque.
claimed_id parsing collisions. SteamID64 is 17 digits and stable — good. But if you have an existing users table with a shared external-ID column, or users who previously linked another provider, you need an explicit linking policy and a unique constraint on steam_id before you go live. Silent re-assignment of an existing account is the failure mode.
No Laravel-native contract exists. No facade, no guard driver, no Auth::loginUsingSteam. You will write the session login, the user mapping, and the routes. That's fine — it's small — but budget it as work, not as "install and configure."
Watch for stale PHP/Guzzle pins during any framework bump. If you did vendor the bundle, this surfaces late and silently — a Laravel or Symfony major-version upgrade will fail to resolve and you'll be reading the bundle's composer.json at the worst possible moment.
Don't confuse auth with player data. The single most common mis-scope with this package is expecting profile/inventory/ban data to come back with the login. It returns a verified SteamID64 and nothing else. GetPlayerSummaries and friends are separate integrations with separate API keys and rate limits.
How can I help you explore Laravel packages today?