NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

The package dispatches lifecycle events through the container’s event dispatcher (a no-op when none is bound), so hosts can audit, meter or alert without forking. Payloads are minimal and carry no token strings, secrets or keys:

EventWhenPayload
UserTokenIssuedA user token (access, challenge, verify or custom) is minted.subject, scope, jti, expiresAt
ServiceTokenIssuedA service token is issued.issuer, audience, jti, expiresAt
TokenVerificationFailedAn explicit Jwt::verify() fails.reason, exceptionClass
TokenDeniedA jti is added to the denylist.jti, until

All four are final readonly classes under RoundlyConsulting\Jwt\Events:

use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Jwt\Events\TokenVerificationFailed;
use RoundlyConsulting\Jwt\Events\UserTokenIssued;

Event::listen(function (UserTokenIssued $event): void {
    logger()->info('token issued', [
        'sub'   => $event->subject,
        'scope' => $event->scope,
        'jti'   => $event->jti,
        'exp'   => $event->expiresAt->toIso8601String(),
    ]);
});

Event::listen(function (TokenVerificationFailed $event): void {
    logger()->warning('token verify failed', [
        'reason' => $event->reason,
        'type'   => $event->exceptionClass,
    ]);
});

TokenVerificationFailed fires only from the explicit Jwt::verify() path — never from the guards’ silent per-request resolution, so anonymous probes don’t spam it.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.