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

Hej Laravel Package

renoki-co/hej

Hej is a Laravel package for adding user invitations to your app. It provides invite codes, acceptance flows, expiration, and Eloquent integration so you can build invite-only registration quickly and cleanly.

View on GitHub
Deep Wiki
Context7

Getting Started

Hej is a Socialite wrapper: it ships the OAuth redirect/callback routes, a controller that maps provider payloads onto your user + a social-account record, and the config that drives it. 4.0.0 is a breaking release — plan a config re-publish before you touch anything else.

  1. Check your floor. Laravel 8.x is dropped in 4.0. You need Laravel 9+ and a matching PHP version; composer require renoki-co/hej:^4.0 will fail on 8.x and that's intentional, not a resolution bug.
  2. Install and publish.
    composer require renoki-co/hej
    php artisan vendor:publish --tag="hej-config"
    php artisan vendor:publish --tag="hej-migrations"
    php artisan migrate
    
  3. Merge the new config keys (required for 4.0). The config now owns two things that used to be implicit: the list of allowed providers and the redirect targets. If you copied an old config/hej.php forward, the package will boot but every login attempt will bounce — an unlisted provider is treated as unknown. Diff your config against the published stub rather than editing over the top.
  4. Wire up provider credentials in config/services.php (github, google, gitlab, …) plus the usual *_CLIENT_ID / *_CLIENT_SECRET / *_REDIRECT_URI env vars. The redirect URI must exactly match what's registered with the provider.
  5. First use case — GitHub login in ten minutes. Add the GitHub client block, add github to the allowed-providers array in hej.php, set the success redirect to /dashboard, then hit /auth/github/redirect. You should land back on the callback, get a user, and see a social-account row.

Where to look first, in order: config/hej.php (the whole 4.0 migration lives here), the package's route registration (to learn the route names so you can route('hej.redirect', $provider) instead of hardcoding URLs), the callback controller (your extension point now), and the social-account model (which lost $fillable in this release).

Implementation Patterns

Subclass the callback controller — that is the sanctioned extension point. With $fillable removed from the model, mass assignment no longer carries your custom columns, so the "add a field" workflow moved into the controller. Extend the package controller, override the method that persists the account, set your attributes explicitly, and point the package route at your class (via the config's controller/route binding or by declaring your own routes).

class HejController extends \RenokiCo\Hej\Http\Controllers\HejController
{
    protected function updateSocialAccount($account, $providerUser)
    {
        $account->forceFill([
            'nickname' => $providerUser->getNickname(),
            'avatar'   => $providerUser->getAvatar(),
        ]);

        return parent::updateSocialAccount($account, $providerUser);
    }
}

Drive redirects from config, not the controller. The new redirects section exists so that SPA/Inertia/Livewire flows can point at a front-end route without forking the controller. Keep environment-specific destinations (local /dashboard, prod /onboarding) in config/hej.php and out of code. If the config supports per-provider overrides, prefer those over a single global value.

Treat providers as an allow-list, not a discovery mechanism. The allowed array is the security boundary — it prevents /auth/{anything}/redirect from spinning up arbitrary Socialite drivers. Register only what you actually ship, and gate additions behind a config review rather than editing in production.

Multi-provider linking. Model the social account as (provider, provider_id) → user_id and let one user hold several rows. In the callback, look up by provider + provider_id first; fall back to email-match for account linking; only then create a new user. This is where most real bugs land — decide up front whether a second provider with a matching email auto-links or prompts.

Custom routes for prefixes and throttling. Disable the package routes and declare your own on a group with prefix('auth'), middleware(['web', 'throttle:10,1']), pointing at your controller subclass. Good for localization (/{locale}/auth/...) and for keeping the callback out of broad middleware.

Stateless / API mode. For SPA or mobile, don't use the session-based redirect route at all — call Socialite statelessly from your own endpoint and have your controller subclass mint a Sanctum token in the callback instead of logging in. The config-driven redirects are then largely bypassed, which is fine; return JSON.

Testing. Fake Socialite rather than the network:

Socialite::shouldReceive('driver->user')->andReturn($fakeProviderUser);

Assert three things per provider: the redirect route 302s to the provider, the callback creates exactly one social-account row, and a repeat callback updates rather than duplicates.

Gotchas and Tips

  • The config change is not optional. 4.0's config is the release's main breaking surface. Symptoms of a stale config: routes exist but every callback fails, providers "not supported", or redirects dumping users on /. Republish, diff, merge — don't hand-patch.
  • $fillable removal fails quietly in the worst way. SocialAccount::create($providerUser->toArray()) no longer throws a visible mass-assignment error in every path; if the attributes aren't fillable they're simply dropped, and you get a row with nulls. Grep your app for ->create( and ->update( against the package model and switch them to explicit assignment or forceFill.
  • Anything that relied on protected attributes now needs the controller. If a column exists in the DB but never appears in the provider payload mapping, the fix is in your controller subclass, not in the model.
  • Clear caches after upgrading. php artisan config:clear && php artisan route:clear. A cached config from 3.x surviving a composer update is the single most common "4.0 is broken" report.
  • InvalidStateException on callback is almost always a redirect-URI mismatch (scheme, www, port, trailing slash) or a session/cookie-domain problem, not a package bug. Confirm the URI is byte-identical to the provider dashboard entry.
  • Name alignment is exact. The provider key in the allowed list, the Socialite driver name, and the config/services.php key must all agree. google vs google_oauth style drift produces confusing "driver not supported" errors.
  • Open-redirect risk. The new config-driven redirects make it tempting to accept a ?redirect= parameter. Don't — keep destinations server-side unless you validate against an allow-list of paths.
  • Enforce a unique index on (provider, provider_id). Without it, concurrent or retried callbacks create duplicate account rows; the controller's "find or create" can't save you from a race.
  • Extension point beyond the controller: you can publish and swap the model for a custom table, but if you do, keep the controller mapping in sync. A swapped model with an unmodified controller is the classic "new column, always null" trap.
  • Upgrade sequencing. Do the config merge, the controller subclass, and the $fillable audit in one branch before enabling the package in production; the three changes interact and a partial upgrade looks like a routing bug rather than a mass-assignment one.
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.
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
noith/settings