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

Larascord Laravel Package

jakyeru/larascord

Larascord is a Laravel package for Discord OAuth2 authentication. It adds a simple Discord login flow, integrates with Laravel Socialite and your user model, and provides configurable routes, scopes, and callbacks for quick setup.

View on GitHub
Deep Wiki
Context7

Getting Started

Larascord adds "Login with Discord" and Discord guild/role awareness to a Laravel app. The v8.0.0 release adds Laravel 13 support and reworks the internals so the package can be dropped into an existing project (its own User model, its own users table) rather than requiring a fresh install — which is the single most important thing to verify before you follow older tutorials or the v7 docs.

  1. Install the pinned major: composer require valentinneaga/larascord:^8.0 (confirm the exact vendor string on Packagist; v8 is the first release advertising Laravel 13, so check the illuminate/* constraint against your app version before upgrading).
  2. Publish and inspect, don't blind-publish:
    php artisan vendor:publish --tag=larascord-config
    php artisan vendor:publish --tag=larascord-migrations
    
    Read the migration before running it. Because v8 targets existing projects, the schema changes should be additive (Discord columns / a linked-accounts table) — if you see it creating a users table or altering columns you already own, stop and reconcile.
  3. Create the Discord application at discord.com/developers/applications: copy the Client ID/Secret, and add the redirect URI exactly as it appears in php artisan route:list | grep -i discord.
  4. Configure env, typically DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET, DISCORD_REDIRECT_URI, plus a guild ID and bot token if you plan to gate on membership/roles. Map these to whatever keys the published config actually reads.
  5. Wire the model: add the package trait to App\Models\User and confirm the column/attribute names match the migration.
  6. Render the button in your login view (Blade component or directive — check the package views/config, as the name is the most likely thing to have changed in the redesign).
  7. php artisan migrate && php artisan config:cache.

First use case: gated community access — "sign in with Discord, and only members of your server with the Member role get in." That exercises the whole surface (OAuth callback, token storage, guild/role lookup) in one flow, and is the fastest way to validate the v8 install.

Implementation Patterns

  • Role-based authorization via Gate. Translate Discord roles into a single Gate definition and use it everywhere instead of scattering role names through controllers:
    Gate::define('access-premium', fn (User $u) => Larascord::userHasRole($u, 'Premium'));
    
    Keep the role names in config, not literals, so staging and prod servers can differ.
  • Middleware for gating, events for side effects. Put membership checks in route middleware on the authenticated group, and use the package's user-created/updated events to sync profile fields (avatar, username), provision a subscription, or post a welcome message. Listeners keep the callback controller thin and make the behaviour testable.
  • Cache roles, don't poll Discord. Persist the resolved guilds/roles on the user (or a discord_roles table) at login and refresh on a schedule or on-demand. Per-request Discord API calls will hit rate limits the moment you have real traffic.
  • Account linking in existing apps. For an app that already has password/SSO users, treat the Discord callback as linking, not registration: if a user is already authenticated, attach the Discord identity to them; if not, match on verified email and require an explicit confirmation before merging. This is exactly the flow v8's compatibility work is meant to enable, so design it deliberately rather than relying on package defaults.
  • Token issuing for SPAs/mobile. Complete the OAuth dance server-side, then issue a Sanctum token and redirect back to the frontend. Keeps the client secret off the device.
  • Bot-assisted membership. If you need guilds.join (auto-add users to the server on signup), that requires a bot token, the guilds.join scope, and the bot already present in the guild — plan the Discord-side setup as part of the feature, not an afterthought.
  • Testing. Fake the Discord HTTP calls with Http::fake() around the token exchange and /users/@me, then assert against the callback route. Seed the user's cached roles directly so authorization tests never touch the network.

Gotchas and Tips

  • Upgrading from v7 is the real risk here. "Redesign architecture for existing project compatibility" means config keys, trait namespace, published migration contents, view/component names, and possibly the callback route name may have moved. Re-publish to a temp directory and diff against your published copies rather than overwriting; grep your codebase for the facade, trait, directive, and event class names. Test the upgrade on a copy of the real app first.
  • Redirect URI mismatch is the #1 failure. It must be byte-identical to what's registered in the Discord portal — scheme, host, trailing slash, and www all matter, and dev/staging/prod each need their own entry. invalid_client and invalid_grant errors usually trace back to this or a stale secret.
  • Discord tokens are short-lived. Access tokens last ~7 days, refresh tokens rotate on use. If you persist them, cast the columns as encrypted, store the expiry, and refresh before use — a long-lived "remember me" session will otherwise break silently.
  • guilds scope returns partial data. Role checks need the bot token plus the guild members intent; without it, membership/role helpers can return empty results that look like "user has no roles" rather than an error. Log the raw response once during setup so you know which case you're in.
  • Changing scopes doesn't retroactively apply. Users must re-consent; bumping scopes in config will leave existing tokens under-scoped until they log in again. Version your expected scopes and handle the re-auth prompt.
  • Rate limits bite. Discord returns 429 with a retry_after body; respect it and back off, and never call the API inside a Blade view or an accessor.
  • Config caching traps. Env values read at boot are baked in by config:cache; queued listeners and scheduled refreshes can see null credentials if you read env() outside the config file. Always go through config('larascord.*').
  • Sessions and subdomains. The callback is a separate request — make sure the session cookie domain and APP_URL are consistent, or the OAuth state check fails intermittently in production only.
  • Verify state. Confirm the package validates the OAuth state parameter; if the redesign touched the callback controller, re-check CSRF/state handling before shipping.
  • Extension points: override the published views via the views tag, bind your own implementation of the package's user/role resolver in a service provider, and prefer events over editing vendor code so future majors stay upgradeable.
  • Laravel 13 support is forward-looking. If you're on 10/11/12, confirm the v8 constraint still admits your version before upgrading; if you're planning a 13 migration, this release removes a blocker.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core