# `Joken.Config`
[🔗](https://github.com/joken-elixir/joken/blob/v2.7.0/lib/joken/config.ex#L1)

Main entry point for configuring Joken. This module has two approaches:

## Creating a map of `Joken.Claim` s

If you prefer to avoid using macros, you can create your configuration manually. Joken's
configuration is just a map with keys being binaries (the claim name) and the value an
instance of `Joken.Claim`.

### Example

    %{"exp" => %Joken.Claim{
      generate: fn -> Joken.Config.current_time() + (2 * 60 * 60) end,
      validate: fn val, _claims, _context -> val < Joken.Config.current_time() end
    }}

Since this is cumbersome and error prone, you can use this module with a more fluent API, see:

  - `default_claims/1`
  - `add_claim/4`

## Automatically load and generate functions (recommended)

Another approach is to just `use Joken.Config` in a module. This will load a signer configuration
(from config.exs) and a map of `Joken.Claim` s.

### Example

    defmodule MyAuth do
      use Joken.Config
    end

This way, `Joken.Config` will implement some functions for you:

  - `generate_claims/1`: generates dynamic claims and adds them to the passed map.
  - `encode_and_sign/2`: takes a map of claims, encodes it to JSON and signs it.
  - `verify/2`: check for token tampering using a signer.
  - `validate/2`: takes a claim map and a configuration to run validations.
  - `generate_and_sign/2`: combines generation and signing.
  - `verify_and_validate/2`: combines verification and validation.
  - `token_config/0`: where you customize token generation and validation.

It will also add `use Joken.Hooks` so you can easily hook into Joken's lifecycle.

## Overriding functions

All callbacks in `Joken.Config` and `Joken.Hooks` are overridable. This can be used for
customizing the token configuration. All that is needed is to override the `token_config/0`
function returning your map of binary keys to `Joken.Claim` structs. Example from the
benchmark suite:

    defmodule MyCustomClaimsAuth do
      use Joken.Config

      @impl true
      def token_config do
        %{} # empty claim map
        |> add_claim("name", fn -> "John Doe" end, &(&1 == "John Doe"))
        |> add_claim("test", fn -> true end, &(&1 == true))
        |> add_claim("age", fn -> 666 end, &(&1 > 18))
        |> add_claim("simple time test", fn -> 1 end, &(Joken.current_time() > &1))
      end
    end

## Customizing default generated claims

The default claims generation is just a bypass call to `default_claims/1`. If one would
like to customize it, then we need only to override the token_config function:

    defmodule MyCustomDefaults do
      use Joken.Config

      def token_config, do: default_claims(default_exp: 60 * 60) # 1 hour
    end

### Options

You can pass some options to `use Joken.Config` to ease on your configuration:

  - `:default_signer`: a signer configuration key in config.exs (see `Joken.Signer`)

# `encode_and_sign`

```elixir
@callback encode_and_sign(Joken.claims(), Joken.signer_arg() | nil) ::
  {:ok, Joken.bearer_token(), Joken.claims()} | {:error, Joken.error_reason()}
```

Encodes the given map of claims to JSON and signs it.

The signer used will be (in order of preference):

  1. The one represented by the key passed as second argument. The signer will be
  parsed from the configuration.
  2. If no argument was passed then we will use the one from the configuration
  `:default_signer` passed as argument for the `use Joken.Config` macro.
  3. If no key was passed for the use macro then we will use the one configured as
  `:default_signer` in the configuration.

# `generate_claims`

```elixir
@callback generate_claims(extra :: Joken.claims()) ::
  {:ok, Joken.claims()} | {:error, Joken.error_reason()}
```

Generates a JWT claim set.

Extra claims must be a map with keys as binaries. Ex: %{"sub" => "some@one.com"}

# `token_config`

```elixir
@callback token_config() :: Joken.token_config()
```

Defines the `t:Joken.token_config/0` used for all the operations in this module.

The default implementation is just a bypass call to `default_claims/1`.

# `validate`

```elixir
@callback validate(Joken.claims(), term()) ::
  {:ok, Joken.claims()} | {:error, Joken.error_reason()}
```

Runs validations on the already verified token.

# `verify`

```elixir
@callback verify(Joken.bearer_token(), Joken.signer_arg() | nil) ::
  {:ok, Joken.claims()} | {:error, Joken.error_reason()}
```

Verifies token's signature using a Joken.Signer.

The signer used is (in order of precedence):

1. The signer in the configuration with the given `key`.
2. The `Joken.Signer` instance passed to the method.
3. The signer passed in the `use Joken.Config` through the `default_signer` key.
4. The default signer in configuration (the one with the key `default_signer`).

It returns either:

- `{:ok, claims_map}` where claims_map is the token's claims.
- `{:error, [message: message, claim: key, claim_val: claim_value]}` where message can be used
on the frontend (it does not contain which claim nor which value failed).

# `add_claim`

```elixir
@spec add_claim(Joken.token_config(), binary(), fun() | nil, fun() | nil, Keyword.t()) ::
  Joken.token_config()
```

Adds a `Joken.Claim` with the given claim key to a map.

This is a convenience builder function. It does exactly what this example does:

    iex> config = %{}
    iex> generate_fun = fn -> "Hi" end
    iex> validate_fun = &(&1 =~ "Hi")
    iex> claim = %Joken.Claims{generate: generate_fun, validate: validate_fun}
    iex> config = Map.put(config, "claim key", claim)

# `add_hook`
*macro* 

Adds the given hook to the list of hooks passed to all operations in this module.

When using `use Joken.Config` in a module, this already adds the module as a hook.
So, if you want to only override one lifecycle callback, you can simply override it
on the module that uses `Joken.Config`.

# `default_claims`

```elixir
@spec default_claims(Keyword.t()) :: Joken.token_config()
```

Initializes a map of `Joken.Claim`s with "exp", "iat", "nbf", "iss", "aud" and "jti".

Default parameters can be customized with options:

  - `:skip`: do not include claims in this list. Ex: [:iss, :aud]
  - `:default_exp`: changes the default expiration of the token. Default is 2 hours
  - `:iss`: changes the issuer claim. Default is "Joken"
  - `:aud`: changes the audience claim. Default is "Joken"

---

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