# `Sigra.JWT.RefreshToken`
[🔗](https://github.com/sztheory/sigra/blob/v1.20.0/lib/sigra/jwt/refresh_token.ex#L1)

Refresh token management with family-based reuse detection.

Refresh tokens are opaque, hashed tokens stored in the `user_tokens` table
with `context: "api_refresh"`. Each token belongs to a "family" identified
by a UUID. When a refresh token is rotated, the old token is marked as
superseded and a new token is created in the same family.

## Reuse Detection (Auth0 Pattern)

If a superseded token is presented for rotation, the entire token family
is revoked. This detects stolen refresh tokens: if an attacker uses a
stolen token after the legitimate user has already rotated it, the reuse
triggers family-wide revocation, protecting both parties.

## Storage

Token metadata (family_id, scopes, superseded_at) is stored as JSON in
the `sent_to` field of the user_tokens table.

# `create`

```elixir
@spec create(Sigra.Config.t(), struct(), [String.t()], keyword()) ::
  {String.t(), struct()}
```

Creates a new refresh token for the given user.

Returns `{raw_token, token_record}` where `raw_token` is the opaque string
to send to the client.

## Options

- `:user_token_schema` - Required. The Ecto schema module for user tokens.

# `revoke`

```elixir
@spec revoke(Sigra.Config.t(), String.t(), keyword()) ::
  :ok | {:error, :invalid_token}
```

Revokes a specific refresh token by marking it as superseded.

## Options

- `:user_token_schema` - Required. The Ecto schema module for user tokens.

# `revoke_all_for_user`

```elixir
@spec revoke_all_for_user(Sigra.Config.t(), term(), keyword()) ::
  {:ok, non_neg_integer()}
```

Revokes all refresh tokens for a user.

Used when a password is changed to invalidate all existing refresh tokens.

## Options

- `:user_token_schema` - Required. The Ecto schema module for user tokens.

# `revoke_family`

```elixir
@spec revoke_family(Sigra.Config.t(), String.t(), keyword()) ::
  {:ok, non_neg_integer()}
```

Revokes all tokens in a family by marking them as superseded.

## Options

- `:user_token_schema` - Required. The Ecto schema module for user tokens.

# `rotate`

```elixir
@spec rotate(Sigra.Config.t(), String.t(), keyword()) ::
  {:ok, String.t(), struct(), [String.t()]}
  | {:error, :invalid_token | :token_expired | :reuse_detected}
```

Rotates a refresh token: supersedes the old token and creates a new one
in the same family.

Returns `{:ok, raw_new_token, new_record, scopes}` on success.

## Reuse Detection

If the presented token has already been superseded (i.e., it was already
rotated), this indicates token theft. The entire family is revoked and
`{:error, :reuse_detected}` is returned.

## Options

- `:user_token_schema` - Required. The Ecto schema module for user tokens.

---

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