Charon.TokenPlugs.OrdsetClaimHas (Charon v4.1.0)

View Source

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

Ordset requirement

The verified token claims must be properly formatted :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