RevocationFeed
in package
The optional session-revocation feed poller (CONTRACT.md §10.4, contract 1.44 — AXIAM threats T-39 and T-143).
WHAT THIS NARROWS, AND WHAT IT IS NOT
An AXIAM access token is self-contained and valid for up to fifteen minutes, and this SDK verifies it locally. A logout, a role removal or an account disable therefore does not reach a token already in a caller's hands until it expires — §10.2 records that, and the documented answer has been "route the decision through gRPC introspection instead", which is correct and costs a round trip PER REQUEST.
A deployment may publish GET /oauth2/revocations: the base64url-unpadded SHA-256 of
every session id revoked within the last access-token lifetime. A guard that polls it
rejects a revoked session within ONE POLL INTERVAL instead of one token lifetime, for one
cacheable fetch per interval.
It is NOT a control, and every rule below follows from that:
- DEFAULT OFF. Nothing polls unless a caller constructs one and passes it.
- NEVER ON THE REQUEST PATH. isRevoked() answers from the cached set and, at most, refreshes a set the NEXT caller sees.
- NEVER FAIL CLOSED. An unreachable feed, a non-200, a body that does not parse, an
algthis build does not know — every one of them behaves exactly as no feed at all. Not as an empty list: an empty list asserts that nothing has been revoked, which is a guard that silently honours no revocations while appearing to honour them. - IT ONLY EVER REJECTS. Every §10.1 rule runs first and still decides. The feed can turn an accept into a reject and never the reverse.
- A TOKEN WITH NO
sidIS NEVER MATCHED. There is no session behind a client-credentials token, an RPT or a token exchange, and hashingjtiinstead would match nothing while looking like it worked.
Table of Contents
Constants
- DEFAULT_POLL_INTERVAL_SECONDS : mixed = 30
- The interval §10.4 recommends, and the one a feed uses unless told otherwise.
- FEED_PATH : mixed = '/oauth2/revocations'
- The published feed's path, appended to a deployment's base URL.
- MAX_ENTRIES : mixed = 100000
- The largest number of entries kept in the cache (§10.4 rule 2).
- MIN_POLL_INTERVAL_SECONDS : mixed = 15
- The shortest interval a caller may configure (§10.4 rule 2), in seconds.
Methods
- __construct() : mixed
- entryFor() : string
- The feed entry for a `sid`, as the server computes it.
- feedUrl() : string
- The feed document's URL, for diagnostics.
- isRevoked() : bool
- Reports whether this session has been revoked, as far as this poller knows.
- pollIntervalSeconds() : int
- The interval actually in effect, after the MIN_POLL_INTERVAL_SECONDS clamp.
- refresh() : void
- Fetches now, whatever the interval says. For tests, and for a caller that wants the first poll to have happened before it starts serving.
Constants
DEFAULT_POLL_INTERVAL_SECONDS
The interval §10.4 recommends, and the one a feed uses unless told otherwise.
public
mixed
DEFAULT_POLL_INTERVAL_SECONDS
= 30
FEED_PATH
The published feed's path, appended to a deployment's base URL.
public
mixed
FEED_PATH
= '/oauth2/revocations'
MAX_ENTRIES
The largest number of entries kept in the cache (§10.4 rule 2).
public
mixed
MAX_ENTRIES
= 100000
The server bounds the document by its own revocation rate over one token lifetime, so this is defence against a server that stops doing so — a cache with no ceiling is an allocation an unauthenticated endpoint controls. Overflow drops the WHOLE set rather than truncating it: a truncated set is a guard that admits some revoked sessions and reports none, which is worse than a guard that admits all of them and says the feed is unusable.
MIN_POLL_INTERVAL_SECONDS
The shortest interval a caller may configure (§10.4 rule 2), in seconds.
public
mixed
MIN_POLL_INTERVAL_SECONDS
= 15
Bounded because the feed is one deployment-wide document and a fleet of guards polling it at a hundred milliseconds is a load source rather than a security improvement. The floor is applied by CLAMPING, not by refusing: a caller who asked for something faster gets the fastest thing on offer.
Methods
__construct()
public
__construct(ClientInterface $http, string $baseUrl[, int|null $pollIntervalSeconds = null ]) : mixed
Parameters
- $http : ClientInterface
-
used only to fetch the feed document; the same Guzzle client type JwksVerifier takes
- $baseUrl : string
-
the AXIAM server base URL; the feed path is resolved against it. A deployment that does not publish the feed is not an error here — that is discovered on the first poll, and behaves as no feed at all from then on
- $pollIntervalSeconds : int|null = null
-
how long a fetched set is served before a refetch is attempted; clamped UP to MIN_POLL_INTERVAL_SECONDS rather than refused
entryFor()
The feed entry for a `sid`, as the server computes it.
public
static entryFor(string $sid) : string
Base64url without padding over the claim's EXACT string — never a parsed-and-re-rendered UUID, or the answer would depend on this class's UUID parser rather than on the feed.
Parameters
- $sid : string
Return values
stringfeedUrl()
The feed document's URL, for diagnostics.
public
feedUrl() : string
Return values
stringisRevoked()
Reports whether this session has been revoked, as far as this poller knows.
public
isRevoked(string|null $sid) : bool
False whenever the answer is not a confident yes — a feed never fetched, unreachable, malformed, or simply not listing this session. The caller admits the request in all of those cases, which is §10.4 rule 3 and is the whole reason the feature is safe to turn on.
Parameters
- $sid : string|null
-
the
sidclaim, or null/empty for a token that carries none — which is never matched (§10.4 rule 6)
Return values
boolpollIntervalSeconds()
The interval actually in effect, after the MIN_POLL_INTERVAL_SECONDS clamp.
public
pollIntervalSeconds() : int
Return values
intrefresh()
Fetches now, whatever the interval says. For tests, and for a caller that wants the first poll to have happened before it starts serving.
public
refresh() : void