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

Jwt For Laravel Laravel Package

roundly-consulting/jwt-for-laravel

JWT authentication for Laravel: issue, validate, and refresh JSON Web Tokens with configurable guards, middleware, and token handling that integrates cleanly into Laravel applications and APIs.

View on GitHub
Deep Wiki
Context7

Getting Started

This release is entirely test-facing: Jwt::fake() now covers the service-to-service side of the package, not just user impersonation. If you already use Jwt::fake()->actingAs($user), the new API is the same shape, one level down.

  1. Confirm your service guard is wired up. You should have a guard using the service-jwt driver, plus jwt.service.issuers (the allow-list of issuers the guard accepts) and jwt.service.secrets (per-issuer secrets, falling back to a shared secret) in config/jwt.php.
  2. Find your first use case. A feature test that hits an endpoint guarded by service-jwt and expects a 200 rather than a 401. Replace any hand-rolled withHeader('Authorization', 'Bearer '.$token) helper with actingAsService().
  3. Call it:
Jwt::fake()->actingAsService('billing', ['scope' => 'invoices:read']);

$this->getJson('/api/invoices')->assertOk();

By default the token is signed with that issuer's own jwt.service.secrets entry if present, otherwise the shared secret, and is addressed to this service as the audience. Pass a third argument to override the audience for cross-service tests.

  1. Clean up when a test needs to be anonymous again. Jwt::fake()->forgetActing() returns subsequent requests to unauthenticated.

Implementation Patterns

Per-test setup, not per-class. The fake holds acting state across requests within a test. Reset it in setUp()/tearDown(), or in Pest via beforeEach(fn () => Jwt::fake()->forgetActing()), so a service identity never leaks from one test case to the next.

Testing multi-tenant / multi-issuer flows. Because actingAsService($issuer, ...) now mints a token that actually carries the foreign issuer (rather than inheriting jwt.service.issuer), you can write a single test that loops over allowed issuers and asserts identical behaviour, and a companion test that feeds a non-allow-listed issuer and asserts a 401. That negative case is the one hosts previously had to hand-encode to exercise.

Claims as a first-class fixture. Put tenant IDs, scopes, and roles in the $claims array rather than stubbing authorization internals. You are then testing the real guard path end-to-end, signature verification included.

Switch identities mid-test. actingAsService('a') → request → actingAsService('b') → request is supported: the second call replaces the acting identity. Use forgetActing() explicitly when you need to prove the endpoint rejects anonymous callers, rather than relying on the absence of a prior actingAs().

Combine with user impersonation carefully. In a test that exercises a user request and a service request, set the service identity immediately before the service call, then forgetActing() and use actingAs($user) for the user call. Don't assume the fake distinguishes request targets for you.

Integration tip: assert the audience. If the calling service relies on audience validation, write one test with the default audience (this service) and one with a mismatched audience to lock in rejection behaviour.

Keep real outbound tokens out of the fake. The app's own outbound tokens still carry jwt.service.issuer as configured. actingAsService() is a test affordance for simulating an inbound caller, not a way to generate production tokens — don't reach for it outside tests.

Gotchas and Tips

  • withoutToken() will not make you anonymous. The fake re-attaches its bearer to any request lacking an Authorization header, so Laravel's token-stripping helper is silently overridden. forgetActing() is the supported escape hatch — this is the single most likely source of confusing "why is this 200?" failures.
  • The issuer must be on jwt.service.issuers. actingAsService() will happily mint for any issuer string you give it, but the guard still rejects issuers off the allow-list. A 401 after a successful-looking actingAsService() almost always means the issuer is missing from that config array.
  • Secret resolution is ordered. Issuer-specific entry in jwt.service.secrets wins; the shared secret is the fallback. If you rotate the shared secret in .env but an issuer has a stale explicit entry, your test token verifies against the stale secret and the guard fails against the app's real secret. Check both places when signature errors appear.
  • Signing is fixed to HS256. If you're migrating an issuer to another algorithm, the fake will not follow you and will produce tokens the guard rejects. Treat this as a signal that the fake needs extending rather than a test bug.
  • Audience defaults to the current service. Tests that previously hand-built tokens with no aud claim may now behave differently once rewritten to use actingAsService(). Pass null/an explicit value deliberately if the endpoint under test doesn't validate audience.
  • Extension point: if you need additional fake behaviours (expired tokens, malformed payloads), wrap rather than mutate — build a small test helper around Jwt::fake() and reset with forgetActing() in its teardown.
  • Debugging tip: when a service test fails, dump the decoded token from the outgoing request before touching guard configuration — confirming iss, aud, and exp in one place resolves most of these in a single pass.
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.
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox