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 rowUplatnenie 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. Najprv vytvorte nový prístupový token a jeho odkaz odovzdajte v RotationContext:
use RoundlyConsulting\RefreshTokens\DataTransferObjects\RotationContext;
$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: $newAccess->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
}
$plainText = $rotation->newRefreshToken->plainText; // return to the client ONCErotate() 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).
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()
));Správanie pri zlyhaní
Výsledok null (alebo výnimku) chápte 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 a jej najnovší riadok nesmie byť ukončený odvolaním — 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 kryptomienOdoslaní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.