# `Charon.TokenPlugs.OrdsetClaimHas`
[🔗](https://github.com/weareyipyip/charon/blob/v4.3.0/lib/charon/token_plugs/ordset_claim_has.ex#L1)

Verifies that bearer token payload claims contain expected values using `m::ordsets` (ordered set) operations.

> #### Ordset requirement {: .warning}
>
> The verified token claims **must** be properly formatted `m::ordsets`.
> The plug does not validate this - malformed values will produce incorrect results or errors.

Like the other plugs in `Charon.TokenPlugs`, this plug short-circuits if errors have already been added to the connection, and it does not by itself halt the conn.

Must be used after `Charon.TokenPlugs.verify_token_signature/2`.

## Comparison Operations

Two comparison modes are supported:

* `:all_of` (default) - The claim must contain **all** of the expected values
* `:any_of` - The claim must contain **at least one** of the expected values

## Usage

The plug accepts various initialization formats. All claims are converted to string keys,
and expected values are normalized to ordered sets.

Basic usage with keyword lists. This verifies two claims, both with the default `:all_of` operation.

    plug OrdsetClaimHas, scope: ~w(read write), role: "admin"

Explicit operations can be passed along with the expected values.

    plug OrdsetClaimHas,
      scope: [all_of: ~w(read write)],
      role: [any_of: ~w(admin moderator)]

You can also use maps or a tuple to initialize the plug.

    plug OrdsetClaimHas, %{scope: "read"}
    plug OrdsetClaimHas, %{"scope" => "read"}
    plug OrdsetClaimHas, {"scope", "read"}

## Examples

    # Verify token has both "read" and "write" scopes
    iex> opts = OrdsetClaimHas.init(scope: ~w(read write))
    iex> conn()
    ...> |> Charon.Utils.set_token_payload(%{"scope" => ["read", "write"]})
    ...> |> OrdsetClaimHas.call(opts)
    ...> |> Charon.Utils.get_auth_error()
    nil

    # Fails when required claim values are missing
    iex> opts = OrdsetClaimHas.init(scope: "write")
    iex> conn()
    ...> |> Charon.Utils.set_token_payload(%{"scope" => ["read"]})
    ...> |> OrdsetClaimHas.call(opts)
    ...> |> Charon.Utils.get_auth_error()
    "bearer token claim scope invalid"

    #  WARNING: if a token claim is not a proper ordset, this plug will NOT behave as expected!
    iex> opts = OrdsetClaimHas.init(scope: "write")
    iex> conn()
    ...> |> Charon.Utils.set_token_payload(%{"scope" => ["write", "read"]})
    ...> |> OrdsetClaimHas.call(opts)
    ...> |> Charon.Utils.get_auth_error()
    nil

---

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