Search by

roundly-consulting / refresh-tokens-for-laravel

mihaliak

Opaque, rotating refresh tokens and device sessions for Laravel — SHA-256 at rest, atomic anti-double-spend rotation, family revocation on reuse. Zero third-party runtime deps.

Package info

github.com/roundly-consulting/refresh-tokens-for-laravel

pkg:composer/roundly-consulting/refresh-tokens-for-laravel

Fund package maintenance!

Patreon

Statistics

Installs: 10

Dependents: 1

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-10-03 18:12 UTC

This package is auto-updated.

Last update: 2026-10-03 18:33:42 UTC


README

Refresh Tokens for Laravel — Roundly open source

Latest release Tests Code style Donate Patreon Crypto

Refresh Tokens for Laravel

Opaque, rotating refresh tokens and device sessions for Laravel — SHA-256 at rest, atomic anti-double-spend rotation, and whole-family revocation the moment a spent token is replayed. Tokens hang off a polymorphic owner, so any Authenticatable model can hold sessions; JWT minting, user-agent parsing and routes stay in your app.

Installation

Requires PHP 8.4 and Laravel 12 or 13.

composer require roundly-consulting/refresh-tokens-for-laravel
php artisan vendor:publish --tag="refresh-tokens-migrations"
php artisan migrate

If your owner models have UUID/ULID keys, set REFRESH_TOKENS_KEY_TYPE=uuid (or ulid) before migrating.

Usage

Add the trait to every model that holds sessions:

use RoundlyConsulting\RefreshTokens\Traits\HasRefreshTokens;

final class User extends Authenticatable
{
    use HasRefreshTokens;
}

Mint your access token first, then issue a refresh token linked to it and rotate it on refresh:

use RoundlyConsulting\RefreshTokens\DataTransferObjects\RotationContext;
use RoundlyConsulting\RefreshTokens\Facades\RefreshTokens;

$new = RefreshTokens::for($user)->fromRequest($request)->linkedTo($access->jti)->issue();
$new->plainText;                         // hand to the client ONCE — never stored

$rotation = RefreshTokens::rotate($new->plainText, new RotationContext(accessReference: $newAccess->jti));
$rotation->newRefreshToken->plainText;   // the replacement; a null result means "log in again"

RefreshTokens::rotate($new->plainText);  // null — a replayed token revokes the whole session

Manage device sessions:

RefreshTokens::sessions($user)->all();                             // active sessions, newest first
RefreshTokens::sessions($user)->revokeAllExcept($currentFamilyId); // "log out my other devices"
RefreshTokens::revoke($plainFromClient);                           // logout with the token in hand

Documentation

The full documentation — configuration, every feature and its API, and testing — lives on our website: roundly-consulting.com/open-source/docs/refresh-tokens-for-laravel

Release notes are in CHANGELOG.md. To contribute, see the contributing guide.

Support our work

This package is free and open source, built and maintained by Roundly Consulting. If it saves you time, please consider supporting our open-source work — a one-time donation, a monthly pledge on Patreon or a crypto donation helps fund maintenance, new features and new packages.

Donate to Roundly open source Become a patron on Patreon Donate crypto: BTC, ETH, BNB or SOL

License

The MIT License (MIT). Copyright (c) roundly-consulting. See LICENSE.md.