Hook these on the host side; they carry ids and scalars only (plus the reason enum), never the model or the plaintext. ownerType is the owner’s morph class, so listeners can tell account types apart:
| Event | Payload | When |
|---|---|---|
RefreshTokenIssued | tokenId, familyId, ownerType, ownerId | A token is issued — trigger async device/geo enrichment. |
RefreshTokenRedeemed | tokenId, familyId, ownerType, ownerId | A token was legitimately spent (rotated) — audit rotations or meter session churn. |
SessionRevoked | tokenId, familyId, ownerType, ownerId, reason, accessReference | An active row is revoked, or a session caught mid-rotation is sealed. |
RefreshTokenReuseDetected | familyId, ownerType, ownerId, revokedCount | A spent token was re-presented — to redeem or to log out — and something was revoked: a theft signal. |
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\RefreshTokens\Events\RefreshTokenRedeemed;
use RoundlyConsulting\RefreshTokens\Events\SessionRevoked;
Event::listen(function (RefreshTokenRedeemed $event): void {
// $event->tokenId, $event->familyId, $event->ownerType, $event->ownerId
// audit rotations, meter session churn, …
});
Event::listen(function (SessionRevoked $event): void {
// $event->reason is a RevocationReason; $event->accessReference is ?string
// write an audit-trail entry, send a "signed out" notification, …
});All events live in RoundlyConsulting\RefreshTokens\Events. rotate() fires one RefreshTokenRedeemed and one RefreshTokenIssued; RefreshTokenIssued is not fired for a replacement that comes back already revoked.
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 cryptoBy 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.