NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Refresh Tokens for Laravel

Uplatnenie a rotácia

redeem() atomicky uplatní a rotuje token. Zo súbežných uplatnení toho istého tokenu uspeje práve jedno; každé zlyhanie skončí ako null, takže volajúci nerozlíši neznámy, expirovaný, odvolaný či prehratý token:

$result = RefreshTokens::redeem($plainFromClient); // ?RedemptionResult

if ($result === null) {
    // unknown / expired / revoked / race-lost / reuse — host maps to its own error
    throw ValidationException::withMessages(['refresh_token' => 'Please sign in again.']);
}

$owner = $result->user;            // the owner model (User, Client, …)
$familyId = $result->familyId;     // the stable session id
$spent = $result->redeemedToken;   // the now-revoked row

Uplatnenie je jediný UPDATE … WHERE revoked_at IS NULL — compare-and-swap, ktorý serializuje samotná databáza. Bez transakcie a bez zámku riadku; na PostgreSQL aj SQLite funguje rovnako. Úspešné uplatnenie spustí RefreshTokenRedeemed.

Obnova obmedzená na typ účtu

Odovzdajte morph triedu vlastníka, ktorého váš endpoint obsluhuje. Token iného typu sa považuje za neznámy — null, nespotrebuje sa, žiadny signál zneužitia — takže token používateľa predložený na endpointe pre klientov nemôže jeho reláciu zničiť ani spustiť detekciu opätovného použitia:

// POST /auth/refresh — users only
$result = RefreshTokens::redeem($plainFromClient, ownerType: (new User)->getMorphClass());

// POST /clients/refresh — API clients only
$result = RefreshTokens::redeem($plainFromClient, ownerType: (new Client)->getMorphClass());

Rotácia jedným volaním

rotate() spojí uplatnenie a vydanie náhrady v tej istej rodine do jedného volania. Vlastník je známy až po návrate z rotate(), preto si najprv zvoľte ID nového prístupového tokenu, odovzdajte ho v RotationContext a prístupový token potom vytvorte s týmto ID pre $rotation->user:

use Illuminate\Support\Str;
use RoundlyConsulting\RefreshTokens\DataTransferObjects\RotationContext;

$jti = (string) Str::uuid();                // the next access token's id

$rotation = RefreshTokens::rotate($plainFromClient, new RotationContext(
    ownerType: (new User)->getMorphClass(),  // optional guard scope
    ipAddress: $request->ip(),              // current ip/ua replace the inherited ones
    userAgent: $request->userAgent(),
    accessReference: $jti,
    ttl: 3600,                              // optional sliding-lifetime override
    meta: ['auth_time' => $authTime],       // merged over the inherited meta
));
// ?RotationResult { user, newRefreshToken (NewRefreshToken), redeemedFamilyId }

if ($rotation === null) {
    // re-authenticate
}

// … mint the new access token for $rotation->user with $jti …

$plainText = $rotation->newRefreshToken->plainText; // return to the client ONCE

rotate() spustí jednu udalosť RefreshTokenRedeemed pre použitý token a jednu RefreshTokenIssued pre náhradu.

Čo náhrada dedí

Vydanie do existujúcej rodiny — cez rotate() alebo výslovné issue() s familyId — skopíruje reláciu z najnovšieho riadku rodiny, či už je odvolaný, alebo nie:

  • family_started_at a absolute_expires_at — bez zmeny, takže absolútny strop platí pre celú reťaz rotácií.
  • meta — zlúčené s novými metadátami (nové kľúče majú prednosť).
  • Stĺpce zariadenia a polohy — browser, browser_version, os, os_version, device_type, is_bot, country, city, country_code.
  • ip_address a user_agent — z kontextu, ak sú zadané, inak sa tiež skopírujú.

Expirácia náhrady je min(now + ttl, absolute_expires_at).

Expirovanú rodinu nemožno zdediť (InvalidTokenFamilyException::expired): ani po uplynutí jej absolútnej životnosti, ani keď jej najnovší riadok expiroval nepoužitý — rodina bez stropu (absolute_ttl = 0) tak nikdy neožije s novým TTL. Riadok, ktorý len spotrebovala rotácia, zostáva dediteľný, takže uplatnenie → vytvorenie → vydanie funguje, aj keď jeho vlastná expirácia uplynie počas vytvárania prístupového tokenu.

Uplatnenie, vytvorenie, vydanie

Ak musí náhrada odkazovať na prístupový token vytvorený až po uplatnení, rozdeľte volanie — vďaka dedeniu sa táto cesta správa presne ako rotate():

// When the replacement must reference an access token minted AFTER the redeem:
$result = RefreshTokens::redeem($plainFromClient);

if ($result === null) {
    // re-authenticate
}

// … mint the new access token for $result->user as $access …

$new = RefreshTokens::issue($result->user, new IssueContext(
    accessReference: $access->jti,
    familyId: $result->familyId,   // inherit the session — behaves exactly like rotate()
));

Ak sa rodina medzi uplatnením a vydaním ukončila — verdiktom o opätovnom použití, odvolaním alebo uplynutím absolútnej životnosti počas vytvárania prístupového tokenu — issue() vyhodí InvalidTokenFamilyException alebo sa vráti už odvolané: čerstvo vytvorený prístupový token zneplatnite a klienta požiadajte o nové prihlásenie.

Správanie pri zlyhaní

Neplatný kontext alebo konfigurácia — ttl v RotationContext menšie ako 1, accessReference dlhšie ako 64 bajtov alebo neplatná konfigurácia ttl, absolute_ttl či token_length — vyhodí InvalidTokenConfigurationException ešte pred uplatnením, takže predložený token zostane platný a opravené volanie prejde.

Po tomto bode chápte výsledok null (alebo výnimku) ako „prihláste sa znova“. rotate() spotrebuje starý token skôr, než náhrada existuje, a zámerne sa nevracia späť — vrátenie spotrebovaného tokenu by znovu otvorilo priestor na dvojité použitie. Ak sa náhradu nepodarí vytvoriť (výpadok databázy, vlastník zmazaný počas rotácie alebo rodina zrušená súbežnou reakciou na zneužitie), klient jednoducho nemá platný refresh token a prihlási sa znova. Žiadny token sa nikdy nepodvrhne.

Výslovné familyId sa validuje: rodina musí existovať pre toho istého vlastníka, nesmie byť zrušená detekciou opätovného použitia, jej najnovší riadok nesmie byť ukončený odvolaním a nesmie byť expirovaná — inak InvalidTokenFamilyException. Tým sa zabráni pripojeniu tokenu do rodiny iného používateľa alebo do mŕtvej rodiny.

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.