# `Attesto.Federation.TrustMark`
[🔗](https://github.com/XukuLLC/attesto/blob/v2.1.0/lib/attesto/federation/trust_mark.ex#L1)

Verify an OpenID Federation 1.0 Trust Mark JWT.

`Attesto.Federation.EntityStatement`'s `trust_marks` handling only checks
that each entry is *shaped* correctly (non-empty `trust_mark_type` and
`trust_mark` JWT string) - it never verifies the `trust_mark` JWT itself.
This module does that verification: signature, `typ`, `crit`, and the
trust mark's own claims (`iss`, `sub`, `trust_mark_type`, `exp`).

A Trust Mark JWT is signed by a Trust Mark Issuer over claims that at
minimum name the entity it was issued to (`sub`), the Trust Mark Issuer
itself (`iss`), and which mark it asserts (`trust_mark_type`). The caller
supplies the Trust Mark Issuer's JWK Set - obtained and trusted out of
band (e.g. that issuer's own Entity Configuration, itself resolved and
trust-chain-verified), exactly as `EntityStatement.verify/3` requires
trusted signer keys from its caller rather than trusting embedded keys.

Conn-free and fail-closed, like the rest of attesto core.

# `verify_error`

```elixir
@type verify_error() ::
  :invalid_trust_mark
  | :invalid_typ
  | :invalid_alg
  | :unsupported_critical_header
  | :invalid_signature
  | :expired
```

# `verify`

```elixir
@spec verify(String.t(), map() | [map()] | list(), keyword()) ::
  {:ok, map()} | {:error, verify_error()}
```

Verify a Trust Mark JWT's signature and claims.

`trusted_jwks` is the Trust Mark Issuer's JWK Set (`%{"keys" => [...]}`, a
single JWK map, or a list), trusted by the caller out of band - this
function never trusts keys embedded in the token itself. Options:

  * `:accepted_algs` - JWS algorithms accepted for the signature. Defaults
    to `Attesto.SigningAlg.allowed/0`.
  * `:issuer` - if given, the verified `iss` must equal it (the expected
    Trust Mark Issuer).
  * `:subject` - if given, the verified `sub` must equal it (the entity
    the mark was expected to be issued to).
  * `:trust_mark_type` - if given, the verified `trust_mark_type` must
    equal it (the mark the caller asked about).
  * `:now` / `:leeway` - clock reference and skew for the `exp` check.
    `exp` is OPTIONAL on a Trust Mark (revocation may instead be checked
    via the Trust Mark Issuer's status endpoint, out of scope here); when
    present it MUST hold.

Returns `{:ok, claims}` with the trust mark's full claim set on success, or
`{:error, reason}` - a tampered signature, wrong key, expired mark, or a
mismatch against any `:issuer`/`:subject`/`:trust_mark_type` all fail
closed.

---

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