mrgoodbytes8667/discord-client-bundle
A PHP package that bundles a Discord client integration, offering configuration and service wiring to connect your application to Discord’s API. Review the documentation for supported framework versions, setup steps, and available features.
First, the framing: this is a Symfony bundle, not a Laravel package. Composer will install it into a Laravel app, but there is no ServiceProvider, no publishable config, no facade, and no Laravel-aware route registration. So "getting started" splits into two realistic paths:
Path A — you actually run Symfony (microservice, separate auth app, or you're porting a Symfony project):
composer require mrgoodbytes8667/discord-client-bundleconfig/bundles.phpDependencyInjection/Configuration.php in the repo for the exact config keys — the README is thin, the Configuration class is the real documentation)bin/console debug:router | grep -i discord to confirm the login/callback routes exist, then hit the login routePath B — you're a Laravel developer who wants "Login with Discord" (the common case): do not install this. Use laravel/socialite plus socialiteproviders/discord. This bundle is best treated as a reference implementation — read its controller and OAuth client to understand the flow, then implement the ~40 lines of Socialite glue yourself. That gives you Laravel's session/state handling, guard integration, and error handling for free.
First use case either way: redirect the user to Discord → receive code on the callback → exchange for an access token → call /users/@me → persist id, username, global_name, avatar → either create a local user or attach discord_id to an existing one.
Account linking, not account creation, is the safer default. Add a nullable, unique discord_id column to users. On callback, look up by discord_id first; only create a new user if you trust the email (Discord's email scope returns verified and unverified addresses — check the verified flag before treating it as a merge key).
Separate "login" from "link" with an intent parameter. The same callback route serves both. Stash {intent: 'link', user_id: X} in the session before redirecting, and branch on it in the callback. This avoids a second redirect URI and a second route.
Gate on guild membership if you're building a community tool. Request the guilds scope, then call GET /users/@me/guilds with the access token and check for your guild ID. Cache the result for the session lifetime — it's a cheap call but not free, and Discord rate-limits per-route.
Sync roles, don't just authenticate. The highest-value pattern: map Discord guild roles to Laravel roles/permissions, then refresh on login (or on a scheduled job using the stored refresh token). Treat Discord as the source of truth for membership, your app as the source of truth for what that membership unlocks.
Store refresh tokens. Discord access tokens live ~7 days; refresh tokens are long-lived and rotate on use. Encrypt both (encrypted cast), and refresh in a queued job rather than inline in the request — a Discord hiccup shouldn't 500 your login.
Isolate the provider. Register Discord as its own guard/provider so it doesn't collide with your existing email/password flow. Users should be able to have both.
Keep the bot out of this. This package covers OAuth only — no gateway connection, no bot token, no webhooks. If you need bot functionality, that's a separate long-running process (DiscordPHP, discord.js, etc.) talking to your app over HTTP or a queue.
NOASSERTION. That's a red flag for anything commercial. Verify the actual terms in the repo before shipping; if you can't find a clear license file, treat it as all-rights-reserved and port the logic instead.http://localhost:8000/auth/discord/callback and http://localhost:8000/auth/discord/callback/ are different. This is the #1 cause of invalid_request on the callback.?error=access_denied&error_description=... on the callback when the user cancels. Laravel's default validation of a required code param will throw before you can handle the cancel gracefully — check for error first.https://cdn.discordapp.com/avatars/{id}/{hash}.png?size=128. If avatar is null (common), fall back to the default embed avatar: https://cdn.discordapp.com/embed/avatars/{(id >> 22) % 6}.png.code from a query string without validating the state parameter against the session. If you're porting from the bundle, don't copy a flow that skips this.429 with retry_after in the JSON body (and X-RateLimit-* headers). If you're calling /users/@me/guilds at login, wrap it with retry-and-backoff rather than letting a 429 break the login.League\OAuth2\Client\Provider as a service. If you need extra scopes or custom user mapping, decorate that service rather than editing the bundle — keeps you upgradable.How can I help you explore Laravel packages today?