Attesto.Revocation (Attesto v2.6.1)

Copy Markdown View Source

RFC 7009 - OAuth 2.0 Token Revocation, for refresh tokens.

Revoking a refresh token revokes its entire family (every token descended from the same authorization), the same machinery refresh rotation uses for reuse detection. This module is the deliberate revocation entry point; it runs over an Attesto.RefreshStore.

No-existence oracle (RFC 7009 §2.2)

An invalid, expired, or unknown token does not produce an error: revoke/3 returns :ok regardless of whether the token existed. A revocation endpoint must not let a caller probe which tokens are live, so revoking a token the store has never seen is indistinguishable from revoking a real one.

Client binding (RFC 7009 §2.1)

When the token carries a client_id, only a matching :client_id may revoke its family. A mismatch is the same no-op :ok response as an unknown token, so the revocation endpoint does not reveal another client's token state. A caller that cannot authenticate the client passes allow_missing_client_id?: true. A token issued without a client binding skips the check.

Issuer binding

Passing :issuer confines revocation to a refresh family issued by that exact authorization-server issuer. A mismatch, including a legacy token with no issuer marker, is the same no-op :ok as an unknown token and never mutates the family. Omitting :issuer preserves legacy core behavior.

Access tokens

Attesto access tokens are stateless, short-lived JWTs, so there is no per-token revocation list to consult; revoking them is a host concern (rely on their short TTL, or maintain a jti denylist the resource server checks). This module revokes the stateful, family-backed refresh credential, which is what RFC 7009 revocation is primarily for.

Summary

Functions

Revoke the refresh token token (and its whole family) via store.

Functions

revoke(store, token, opts \\ [])

@spec revoke(module(), String.t(), keyword()) :: :ok

Revoke the refresh token token (and its whole family) via store.

Returns :ok whether or not the token existed (no-existence oracle). When the token carries a client_id, a mismatch or an absent client without allow_missing_client_id?: true is an indistinguishable no-op :ok and never revokes the family.

Options: :client_id (the authenticated revoking client), :allow_missing_client_id?, and :issuer (the expected authorization server issuer).