### Install package and publish migrations Source: https://github.com/roundly-consulting/refresh-tokens-for-laravel/blob/main/README.md Run these commands to install the package, publish its migrations, and run them. Requires PHP 8.4 and Laravel 12 or 13. Set REFRESH_TOKENS_KEY_TYPE=uuid (or ulid) before migrating if your owner models use UUID/ULID keys. ```bash composer require roundly-consulting/refresh-tokens-for-laravel php artisan vendor:publish --tag="refresh-tokens-migrations" php artisan migrate ``` -------------------------------- ### Add HasRefreshTokens trait to model Source: https://github.com/roundly-consulting/refresh-tokens-for-laravel/blob/main/README.md Add the HasRefreshTokens trait to every model that holds sessions. The example shows a User model extending Authenticatable. ```php use RoundlyConsulting\RefreshTokens\Traits\HasRefreshTokens; final class User extends Authenticatable { use HasRefreshTokens; } ``` -------------------------------- ### Manage device sessions Source: https://github.com/roundly-consulting/refresh-tokens-for-laravel/blob/main/README.md Use these methods to list active sessions, revoke all except the current family, or revoke a specific token for logout. ```php 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 ``` -------------------------------- ### Issue and rotate refresh tokens Source: https://github.com/roundly-consulting/refresh-tokens-for-laravel/blob/main/README.md At login, issue a refresh token linked to the access token's jti. On refresh, rotate() returns null to indicate re-login, or provides the new refresh token. Replaying a spent token revokes the whole session. ```php use Illuminate\Support\Str; 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 $jti = (string) Str::uuid(); // the next access token's id $rotation = RefreshTokens::rotate($new->plainText, new RotationContext(accessReference: $jti)); // null means "log in again"; otherwise mint the access token for $rotation->user with $jti $rotation->newRefreshToken->plainText; // the replacement refresh token RefreshTokens::rotate($new->plainText); // null — a replayed token revokes the whole session ```