auth.provider API
    Preparing search index...

    Function createRefreshTokenFamilyRotation

    • RefreshTokenFamilyRotation composition: builds a fresh RefreshTokenFamily aggregate on register, and translates RefreshTokenFamilyStore.updateFamily outcomes into the 4-variant RefreshTokenFamilyRotationOutcome on rotate.

      The replay branch used to abort the CAS and report replayed, leaving the caller (packages/oauth/src/grants/refreshToken.mts) to revoke the family in a SECOND store write. RFC 6819 §5.2.2.3 wants the whole family dead on replay, and two writes cannot deliver that: between "replay detected, aborted" and "family revoked" a parallel request holding the still-active sibling token could complete its rotation and walk away with a fresh access token, which is most of what the family-revoke defence exists to stop.

      So the replay branch now COMMITS { ...current, revoked: true } and tags the decision REASON_REPLAY_REVOKED. The store's compare-and-swap does the rest: the revocation is applied to exactly the state that was inspected, or the CAS loses and re-reads. A sibling rotation is therefore ordered either strictly before the replay was classified (in which case it was a legitimate rotation of the then-active token) or strictly after the family was revoked (in which case it is refused). There is no longer an "in between" for it to land in.

      This is also why the return contract needed a third state: a committed replay-revocation and a committed ordinary rotation are the same { outcome: "committed" }, and a closure variable cannot tell them apart given the adapter is free to invoke the updater more than once per call.

      The already-revoked branch still ABORTS — there is nothing to write, and re-committing an unchanged aggregate would amplify writes on the one path an attacker can drive at will.

      Defence-in-depth on the aborted branch: any abort whose reason is not REASON_ALREADY_REVOKED classifies as replayed. If a future code path adds an abort case and forgets its reason, the safest classification is a reject-class outcome (the caller rejects either way, and replayed also drives the family-revoke fallback).

      Per A3 §6.1 + #274.

      Returns RefreshTokenFamilyRotation