Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a14bfc-9643-7872-aa12-98326dcf25e7
7.8 KiB
Optional online access-token status
Source proposal under KEY-WP-0042, driven by CUST-WP-0080 and existing NK-WP-0048-T34/T42/T43 and RAPPS-WP-0016-T08/T09. Independent issuer/consumer contract review and native admission remain required. Existing deployments are unchanged. This extends the bounded issuer; it does not introduce a broker, approval store, PDP, or a second application-local token registry.
The legacy profile authenticates self-contained JWTs until expiry. That does not establish that an operation's initiating token is still unrevoked. The optional profile adds issuer-owned current access-token status using RFC 7662 introspection and RFC 7009 revocation. It supports access tokens only, without refresh tokens or token exchange.
Enablement and lifecycle
Owner-admitted configuration opts in explicitly:
tokenStatus:
enabled: true
maxEntries: 10000
The issuer must use HTTPS at its existing trusted ingress. The server's internal
HTTP listener and reverse-proxy topology are unchanged; direct HTTP exposure is
not admitted by an HTTPS issuer string. Omitted configuration keeps the existing
expiry-only token/UserInfo contract and advertises no new endpoints. Enabling
status registers /introspect and /revoke, advertises their implemented client
authentication methods, and connects the same store to issuance and UserInfo.
Human PKCE and service grants add a cryptographically random jti to each access
token. Online human PKCE ID tokens add at_hash, binding the exact access token
using the RS256 rule in OIDC Core 3.1.3.6/8.
The ID token keeps its relying-party audience and omits access-only jti/scope;
the access token keeps its registered resource audience and omits at_hash.
Existing assurance/tenant provenance and the disabled legacy ID-token contract
remain unchanged. Consumers of this online human profile require the exact signed
hash before treating an ID token and access token as one grant; equal identity
facts or issuance seconds alone cannot distinguish separate grants.
Distinct grants in the same second have distinct bearer tokens: a new grant can
never remint a revoked token. A successful response is emitted only after the
token hash, expiry and current registration commitment have been recorded. No
bearer, client secret or identity/group snapshot is retained in the status store.
The store is bounded to the configured count (default 10000, maximum 1000000). Live records and revocation tombstones are never evicted to admit another grant; capacity exhaustion refuses issuance with a fixed 503. Expired entries are collected when admitting a new token. Capacity and per-client ingress rate limits need workload-representative admission: this is not a throughput/availability claim or protection against an authorized client filling the bound.
This profile uses KeyCape's existing single-instance topology. Status is process-local. Restart, deployment, rollback or store loss makes every earlier token inactive at online endpoints, even if its JWT signature/expiry still validates offline. Consumers must reauthenticate; there is no recovery replay or token-state import that can resurrect revoked authority. Multiple replicas are unsupported. Native admission must include this interruption and the measured reauthentication/recovery procedure. A persisted/shared store is not introduced here.
Introspection and revocation
Both endpoints accept POST form bodies only, bound to 64 KiB; token values are
bound to 32 KiB. Query parameters, duplicate form or authentication fields,
unsupported content types and malformed authentication refuse without echoing
input. Responses use Cache-Control: no-store and Pragma: no-cache.
Introspection requires the existing registered confidential client's
client_secret_basic authentication. Only that client's own issued tokens can
be inspected. A separate resource audience is returned as aud, not confused
with the issuing client_id. Cross-client resource-server delegation needs a
separately reviewed authorization contract and is not implicitly granted by a
matching audience string. Public clients cannot enumerate token status.
An active response means the exact access token was issued in this process,
has not expired or been revoked, still matches its current complete registration,
and passes current issuer/signature/purpose validation. For humans, directory
lookup must succeed and the current account must be enabled and not suspended.
Status is checked again after directory lookup. Service subjects remain bound
to their current registration. Active output contains only standard access-token
metadata; inactive output contains only active: false. Unknown tokens, ID
tokens, altered tokens, another client's tokens and expired/revoked tokens all
return that same inactive response to an authenticated introspector.
Revocation authenticates confidential clients using the same method. A registered
public client may revoke its own token using client_id plus possession of that
bearer; public-client introspection remains unavailable. Revocation only affects
the exact token issued to that client. Unknown, other-client, expired and already
revoked tokens all produce the same empty 200. No token existence is disclosed.
Token-type hints do not bypass the actual access-token lookup. Removal or changes
to a registration invalidate online status; the commitment explicitly includes
the secret digest and internal token lifetime omitted from public Client JSON.
When enabled, actual UserInfo consults the same store before lookup and again after it. Revocation therefore affects that existing endpoint immediately on its next check. Ordinary login/logout and upstream Authelia sessions are distinct: neither browser logout nor deleting a local cookie is represented as global JWT revocation.
Consumer contract and remaining acceptance
Online status establishes current access-token status, not permission for an application resource or privileged effect. Consumers still independently validate the actual signed token, admitted issuer/key/audience/type, subject, tenant, principal type, assurance and freshness. The authenticated introspection response must refer to that exact token/client. Obtain a new current response before each protected operation; unavailable, malformed, inactive or ambiguous responses refuse. A cached positive is not a current-session check.
Access Engine retains resource/action decisions, Approval Engine exact one-shot approval, Warden admission and owner adapters execution. Bind their existing descriptor, case, transaction and exact effect before dispatch. A separate new operation/inverse token must be acquired and revoked on every terminal path; renewed authentication cannot revive a consumed approval or replay a mutation. This issuer capability alone implements none of those consumer bindings.
The producer-owned current-token client supplies the shared Go/CLI transport and cryptographic/status join. Its private observations retain this distinction: an inactive-for-client result is not an original ownership or execution receipt. Native client/profile adoption remains open.
Native completion still requires independent issuer/profile review, exact image/config/trust admission, bounded retained-token custody, real human/service issuance, private transport, current-token/revocation integration in each owner, all exit-path cleanup, restart/expiry/unavailable/refusal checks, ongoing HTTP/API/Git/SSH authorization and audit evidence. Offline consumers which never consult the endpoint retain their existing JWT validity; no estate-wide immediate revocation claim follows from source implementation. Disabling the feature is not an acceptable fallback for a consumer admitted under the online profile.