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

Bearer Laravel Package

ryangjchandler/bearer

A lightweight Laravel package for issuing and authenticating bearer tokens, letting you protect API routes with token abilities and expiration—no full OAuth setup required.

View on GitHub
Deep Wiki
Context7

Getting Started

ryangjchandler/bearer is a lightweight bearer-token authentication layer for Laravel — closer to "Sanctum's token API without the SPA/session machinery" than to Passport. v2.1.1 is a compatibility-only patch (adds Laravel 13.x to the constraint), so it changes nothing about how you use it.

Minimal setup:

composer require ryangjchandler/bearer
php artisan vendor:publish --tag=bearer-config   # check the tag in the README first
php artisan migrate                              # only if your config uses DB-backed tokens

First places to look:

  1. config/bearer.php — this is where the token model/table, hashing, and any expiry settings live. Read it before writing a single line of auth code; most confusion about this package comes from assuming defaults that live here.
  2. The Bearer facade — the public extension surface (authenticateUsing, token creation/lookup hooks). Treat this as the package's real API; the config is mostly data.
  3. Your routes/api.php — the middleware is where the package actually enters the request lifecycle.

First use case: issue a token at login, send it as Authorization: Bearer <token>, protect a route group with the package's middleware alias (bearer), and resolve the user with $request->user() exactly as you would with any other guard. If $request->user() is null inside the group, the middleware isn't applied or is ordered after something that short-circuits — see Gotchas.

Implementation Patterns

Issue tokens at a single choke point. Put creation in one action/service (IssueToken) rather than in each controller. Return the plaintext token exactly once in the response, persist only what the package stores, and never re-emit it from a "list my tokens" endpoint.

Group, don't sprinkle. Apply the middleware to the whole API group in bootstrap/app.php (Laravel 11+) or Kernel.php (10.x), then opt individual routes out with ->withoutMiddleware(...) where you need public access. Per-route middleware is the fastest way to end up with one unprotected endpoint.

Abilities/scopes over role checks. If you're using token abilities, gate at the route layer (middleware('bearer:posts:write') or an ability-check middleware) rather than scattering if statements in controllers. Keep the ability string list in a PHP enum so issuance and checking can't drift apart.

Custom resolution closure. The most common real-world pattern is overriding user resolution so you can enforce things the package can't know about — tenant scoping, a revoked_at column, a plan downgrade, a soft-deleted user:

Bearer::authenticateUsing(function ($request, $token) {
    $user = User::whereKey($token->user_id)->whereNull('suspended_at')->first();
    abort_unless($user, 401);
    return $user;
});

Register this in a service provider, not in a controller — it's global state and must be deterministic.

Coexistence with Sanctum. It's common to keep Sanctum for first-party SPA sessions and use Bearer for machine clients. If you do, be explicit per route group which guard applies; two token systems resolving $request->user() with different auth guards is the top source of "wrong user" bugs.

Testing. Hit the real middleware in feature tests with a real header — $this->withHeader('Authorization', "Bearer {$token}") — rather than actingAs(). actingAs() bypasses the package's token lookup entirely and will let a broken token path ship green.

Gotchas and Tips

  • Upgrading to v2.1.1: nothing to do beyond bumping the constraint if you're on Laravel 13. If you're not, stay on ^2.1 and take the patch anyway — there are no behavioural changes, so it's a zero-risk bump. Do check that your other auth packages (Sanctum/Passport) already allow Laravel 13 before upgrading the framework itself; that's the real blocker, not this release.
  • Middleware ordering. If you have a global auth middleware registered before bearer, it will reject the request before the token is ever read. The bearer middleware must run before anything that calls $request->user() or auth()->user().
  • Config caching. php artisan config:cache in deploy will freeze config/bearer.php. If you change token settings and behaviour doesn't move, that's almost always why — config:clear locally, and re-run the cache step in CI.
  • last_used_at-style writes. If your config/model touches the token row on every request, you've turned every read endpoint into a write. Either disable it or debounce it (cache a "touched recently" flag) before this becomes your database's hottest table.
  • Expiry and revocation are your job. The package resolves tokens; it doesn't necessarily expire them. Enforce expiry in the resolution closure so it applies uniformly, and make sure revocation is checked there too — not in individual controllers.
  • Queue workers and Octane. Long-lived processes cache resolved users and config. Restart workers (queue:restart) after deploying auth changes, and be careful with any per-request user caching under Octane.
  • Extension points worth knowing: a custom token model (to add columns), the resolution closure, and a custom ability-check middleware. Everything else is intentionally thin — if you find yourself fighting the package, you probably want Sanctum's guard model instead.
  • Debugging tip: when a request 401s unexpectedly, check in this order — header format (no trailing whitespace, exact Bearer prefix), middleware presence on the route (php artisan route:list -v), then the resolution closure (temporarily Log::info the token lookup result). That covers ~95% of cases.
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.
jinas/dhivatar
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