# `Attesto.Revocation`
[🔗](https://github.com/XukuLLC/attesto/blob/v0.13.0/lib/attesto/revocation.ex#L1)

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`, revocation is fail-closed: the
caller MUST present a matching `:client_id` or the call returns
`{:error, :unauthorized_client}`, so one client cannot revoke another
client's tokens. A caller that cannot authenticate the client passes
`allow_missing_client_id?: true`. A token issued without a client
binding skips the check.

## 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.

# `revoke_error`

```elixir
@type revoke_error() :: :unauthorized_client
```

# `revoke`

```elixir
@spec revoke(module(), String.t(), keyword()) :: :ok | {:error, revoke_error()}
```

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

Returns `:ok` whether or not the token existed (no-existence oracle).
Returns `{:error, :unauthorized_client}` only when the token carries a
`client_id` and the presented `:client_id` does not match (or is absent
without `allow_missing_client_id?: true`).

Options: `:client_id` (the authenticated revoking client) and
`:allow_missing_client_id?`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
