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

Open source

Refresh Tokens for Laravel

Install
composer require roundly-consulting/refresh-tokens-for-laravel
Requires: PHP ^8.4 · Laravel ^12.0|^13.0

Overview

Opaque, rotating refresh tokens and device sessions for Laravel. Tokens are stored only as SHA-256 digests, rotated by a single-query compare-and-swap so exactly one concurrent refresh wins, and replaying a spent token revokes its whole family automatically. Any Authenticatable model — users, API clients, admins — holds sessions in one polymorphic table, with a stable session id, device data and one-call “log out everywhere”. MIT-licensed, with zero third-party runtime dependencies — just Laravel plus Roundly’s own crypto, enums and toolkit packages.

What you get

Hashed at rest

Only a SHA-256 digest is stored under a unique index; the plaintext is returned once. Optional HMAC pepper on top.

Atomic rotation

A single-query compare-and-swap: of N concurrent refreshes exactly one wins — no transaction, no row lock.

Reuse detection

Replaying a rotated token revokes the whole family, denies its access tokens and fires an alert event. Always on.

Device sessions

A stable session id per login, device and geo data, and one-call revoke of one, all others or every session.

Polymorphic owners

Users, API clients, admins — any Authenticatable model shares one table, with guard-scoped redemption.

Sliding + absolute lifetimes

A sliding TTL per rotation plus a hard absolute cap per session, both overridable per login.

Facade, DI or actions

One RefreshTokens facade over an injectable manager and single-purpose actions, plus a recording fake that still runs every call.

Documentation

Installation

Install via Composer, publish and run the migration, and add the HasRefreshTokens trait to every owner model.

Configuration

Every config key, default and env variable — table, key type, lifetimes, token length, hashing, rotation grace and pruning.

Owners & key types

Polymorphic owners: users, API clients and admins share one table, isolated by morph class and key, on bigint, UUID or ULID keys.

The RefreshTokens facade

The whole RefreshTokens facade at a glance — issue, redeem, rotate, revoke and prune, plus the sessions() and session() handles.

DI and actions

Inject RefreshTokensManager instead of calling the facade, or run the action behind any method — the same code either way.

Issuing tokens

Issue a refresh token linked to your access token via IssueContext or the fluent builder; the plaintext is returned exactly once.

Redeeming & rotating

Atomically redeem a token with anti-double-spend, rotate it in one call, scope redemption to one owner type, and handle failures.

Reuse detection

Replaying a rotated token revokes the whole family, denies its access tokens and fires RefreshTokenReuseDetected — always on.

Revocation & logout

Log out one token or every session, record why with RevocationReason, and revoke everything on a password change.

Sessions

List, find and revoke device sessions by their stable family id — the machinery behind a “your devices” screen.

Device & location enrichment

Attach host-parsed browser, OS, device type and geolocation to a session with enrich() — typically from an async job.

Access-token revocation

Bind an AccessTokenRevoker so every revoked session or family also kills its paired access token, e.g. via a JWT jti denylist.

Events

Four typed events — issued, redeemed, revoked and reuse-detected — carrying ids and scalars only, never the model or plaintext.

Security & hashing

SHA-256 digests at rest, an optional HMAC pepper, validated config, serialization safety and the host-owned boundary.

The token model

Scopes, helpers, casts and hidden attributes on the RefreshToken model, and how to swap in your own subclass.

Database schema

The refresh_tokens columns, plus RefreshTokenBlueprint for reproducing or adopting the schema in your own migration.

Artisan commands

Prune dead tokens on your own schedule with refresh-tokens:prune or a named model:prune, and inspect config with about.

Exceptions

Every typed exception the package throws, when it throws, and the base class to catch them all.

Testing

RefreshTokens::fake() records every issue, redeem, rotate, revoke, enrich and prune; FakeAccessTokenRevoker and the factory cover the rest.

Requirements

PHP 8.4+ and Laravel 12 or 13, with zero third-party runtime dependencies. Companion Roundly packages install automatically.

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.