pub struct RefreshRotator<'s, S: RefreshStore + ?Sized> { /* private fields */ }Expand description
Mint and rotate refresh tokens against a RefreshStore.
Holds a borrow of the store; the rotator itself is cheap to construct
per request. ttl_seconds is the lifetime applied to every freshly
minted token (root and successor).
Implementations§
Source§impl<'s, S: RefreshStore + ?Sized> RefreshRotator<'s, S>
impl<'s, S: RefreshStore + ?Sized> RefreshRotator<'s, S>
pub fn new(store: &'s S, ttl_seconds: i64) -> Self
pub fn ttl_seconds(&self) -> i64
Sourcepub async fn mint_root(
&self,
user_id: UserId,
device_id: DeviceId,
now: i64,
) -> Result<Rotated, RefreshError>
pub async fn mint_root( &self, user_id: UserId, device_id: DeviceId, now: i64, ) -> Result<Rotated, RefreshError>
Start a fresh chain. Returns the root token + persisted record.
Sourcepub async fn rotate(
&self,
presented: &str,
now: i64,
) -> Result<Rotated, RefreshError>
pub async fn rotate( &self, presented: &str, now: i64, ) -> Result<Rotated, RefreshError>
Rotate presented → fresh successor.
Failure modes (in priority order):
RefreshError::Unknown— no record matches.RefreshError::ChainRevoked— record exists but the chain is dead.RefreshError::Replay— the token was already consumed; the chain is revoked as a side effect of this call.RefreshError::Expired— within TTL is required.
Equivalent to check followed by
commit; split callers use the gap between the two to
refuse a rotation without spending the token.
Sourcepub async fn check(
&self,
presented: &str,
now: i64,
) -> Result<LiveRefresh, RefreshError>
pub async fn check( &self, presented: &str, now: i64, ) -> Result<LiveRefresh, RefreshError>
Phase one of a rotation: look presented up and prove it is spendable,
without spending it.
Every failure of rotate except a lost consume race
surfaces here — including replay, whose chain revocation happens here
as a side effect. A successful check mutates nothing, so a caller that
decides not to commit (R730: no device binding to
mint with) leaves the chain exactly as it found it.
Sourcepub async fn commit(
&self,
live: LiveRefresh,
now: i64,
) -> Result<Rotated, RefreshError>
pub async fn commit( &self, live: LiveRefresh, now: i64, ) -> Result<Rotated, RefreshError>
Phase two of a rotation: spend the checked token and issue its successor on the same chain.
The LiveRefresh argument can only come from check,
so a commit is always preceded by the full validity check. The check
result is a snapshot, though, and the consume below is the real gate.
Sourcepub async fn revoke_chain(&self, chain_id: &str) -> Result<(), RefreshError>
pub async fn revoke_chain(&self, chain_id: &str) -> Result<(), RefreshError>
Revoke every token in chain_id. Idempotent. Use on logout or
device-revoke flows.