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

Supabase Auth Bundle Laravel Package

kyzegs/supabase-auth-bundle

Laravel bundle that integrates Supabase Auth into PHP apps: verifies Supabase-issued JWTs, syncs users, and adds guards and middleware for protecting routes. Includes drop-in configuration for email/password and OAuth-based sessions, designed for quick setup in Laravel projects.

View on GitHub
Deep Wiki
Context7

Getting Started

composer require kyzegs/supabase-auth-bundle
php artisan vendor:publish --tag=supabase-auth-config   # confirm the tag in the README

Set the environment values the bundle reads (typical names — verify against config/supabase-auth.php once published):

SUPABASE_URL=https://<project>.supabase.co
SUPABASE_ANON_KEY=...
SUPABASE_JWT_SECRET=...

Then wire the guard in config/auth.php:

'guards' => [
    'supabase' => [
        'driver' => 'supabase',
        'provider' => 'users',
    ],
],

Where to look first: the published config file (it enumerates every knob you'll need), the package's service provider (shows what it binds — guard driver, user resolver, middleware aliases), and the tests/ directory if one ships, which is the fastest way to see the expected token shape.

First use case: protecting a stateless API route with the access token your frontend already gets from supabase-js.

Route::middleware('auth:supabase')->get('/api/me', fn () => request()->user());

That single route proves the whole chain: token extraction, signature verification, claim parsing, and user resolution. Once it returns a populated user, everything else is configuration.

Implementation Patterns

Keep authentication in Supabase, authorization in Laravel. Supabase owns credentials, MFA, and token issuance; your Laravel app owns roles, permissions, and business rules. Don't mirror password hashes locally — store a supabase_id (the sub claim) on users and let the guard resolve it.

Verify locally, not over the network. A guard that calls GET /auth/v1/user on every request adds a round trip to every API call. Signature verification against the JWT secret is microseconds. Reserve remote validation for high-risk operations (password change, payment) where you need to confirm the token hasn't been revoked.

Provision users lazily. A resolver that does User::firstOrCreate(['supabase_id' => $claims->sub], [...]) keeps your table in sync without a webhook. Add a webhook or scheduled sync only when you need profile data to exist before the user's first request.

Layer middleware by claim, not by table lookup.

Route::middleware(['auth:supabase', 'verified'])->group(function () {
    Route::middleware('can:admin')->group(function () {
        // routes gated on a role claim
    });
});

Test with real tokens, not mocks. Sign a JWT in your test suite using the same secret from phpunit.xml, and hit the route normally. This catches algorithm mismatches, expiry handling, and claim-name typos that a mocked guard silently hides.

$token = JWT::encode(['sub' => $user->supabase_id, 'exp' => now()->addHour()->timestamp], config('supabase-auth.jwt_secret'), 'HS256');
$this->withHeader('Authorization', "Bearer {$token}")->getJson('/api/me')->assertOk();

Separate the service-role key from the guard. The service role bypasses RLS entirely. It belongs in queued jobs and admin commands, never in the config the request-time guard reads, and never in anything that could be echoed into a response.

Gotchas and Tips

HS256-only verification is the biggest trap. Newer Supabase projects issue asymmetric keys (RS256/ES256) and expose a JWKS endpoint. A package that only supports a shared SUPABASE_JWT_SECRET will reject every token from those projects. Confirm which mode you're in before debugging anything else — decode a real token's header and look at alg.

Never trust user_metadata for authorization. It's user-editable through the Supabase client. Roles belong in app_metadata, which only the service role can write.

Pin the algorithm. Reject alg: none and any algorithm you didn't configure. Algorithm-confusion bugs in JWT libraries are old but still shipped.

Allow clock skew. A 30–60 second leeway on exp/nbf prevents sporadic 401s on hosts with drifting clocks.

401 vs 403 matters for your SPA. If the guard returns 401 for an expired token, supabase-js refreshes and retries. If it returns 403, users get logged out for no reason. Check what the middleware actually emits.

RLS does not apply to your Laravel queries. The bundle authenticates the request; it does not make your Eloquent queries tenant-safe. If you use the service role for database access, row-level security is off and every ->get() is unscoped.

Debugging order: php artisan route:list --middleware=auth:supabase to confirm the guard is attached → config('auth.guards.supabase') to confirm the driver name → decode the token at jwt.io to check alg, exp, aud, and sub → only then read the package source. Ninety percent of failures are one of the first three.

Extension points: the user resolver and the guard driver are the two things you'll realistically want to override — bind your own implementation in a service provider rather than editing the published config, so composer update stays clean.

On v1.0.1: the release notes are a bare compare link with no itemized changes, so treat it as an undocumented patch. Pin "kyzegs/supabase-auth-bundle": "^1.0", and read the diff at the linked compare URL before upgrading if you've already customized the guard — a patch bump implies no breaking changes, but with no changelog text that's an inference, not a guarantee.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource