# `AshAuthentication.Jwt`
[🔗](https://github.com/team-alembic/ash_authentication/blob/main/lib/ash_authentication/jwt.ex#L5)

Uses the excellent `joken` hex package to generate and sign Json Web Tokens.

## Configuration

There are a few things we need to know in order to generate and sign a JWT:

  * `signing_algorithm` - the crypographic algorithm used to to sign tokens.
  * `token_lifetime` - how long the token is valid for (in hours).
  * `signing_secret` - the secret key used to sign the tokens.

These can be configured in your resource's token DSL:

```elixir
defmodule MyApp.Accounts.User do
  # ...

  authentication do
    tokens do
      token_lifetime 32
      signing_secret fn _, _ ->
        System.fetch_env("TOKEN_SIGNING_SECRET")
      end
    end
  end

  # ...
end
```

The signing secret is retrieved using the `AshAuthentication.Secret`
behaviour, which means that it can be retrieved one of three ways:

1. As a string directly in your resource DSL (please don't do this unless you
   know why this is a bad idea!), or
2. a two-arity anonymous function which returns `{:ok, secret}`, or
3. the name of a module which implements the `AshAuthentication.Secret`
   behaviour.

Available signing algorithms are EdDSA, Ed448ph, Ed448, Ed25519ph, Ed25519, PS512, PS384, PS256, ES512, ES384, ES256, RS512, RS384, RS256, HS512, HS384 or HS256.  Defaults to HS256.

We strongly advise against storing the signing secret in your mix config or
directly in your resource configuration.  We instead suggest you make use of
[`runtime.exs`](https://elixir-lang.org/getting-started/mix-otp/config-and-releases.html#configuration)
and read it from the system environment or other secret store.

The default token lifetime is 168 and should be
specified in integer positive hours.

# `claims`

```elixir
@type claims() :: %{
  required(String.t()) =&gt; String.t() | number() | boolean() | claims()
}
```

"claims" are the decoded contents of a JWT.  A map of (short) string keys to
string values.

# `token`

```elixir
@type token() :: String.t()
```

A string likely to contain a valid JWT.

# `default_algorithm`

```elixir
@spec default_algorithm() :: String.t()
```

The default signing algorithm

# `default_lifetime_hrs`

```elixir
@spec default_lifetime_hrs() :: pos_integer()
```

The default token lifetime

# `peek`

```elixir
@spec peek(token()) :: {:ok, claims()} | {:error, any()}
```

Given a token, read it's claims without validating.

# `supported_algorithms`

```elixir
@spec supported_algorithms() :: [String.t()]
```

Supported signing algorithms

# `token_for_resource`

```elixir
@spec token_for_resource(
  Ash.Resource.t(),
  extra_claims :: map(),
  options :: keyword(),
  context :: map()
) ::
  {:ok, token(), claims()}
  | {:error, AshAuthentication.Errors.AuthenticationFailed.t()}
```

Given a resource, generate a signed JWT with a set of claims.

# `token_for_user`

```elixir
@spec token_for_user(
  Ash.Resource.record(),
  extra_claims :: map(),
  options :: keyword(),
  context :: map()
) ::
  {:ok, token(), claims()}
  | {:error, AshAuthentication.Errors.AuthenticationFailed.t()}
```

Given a user, generate a signed JWT for use while authenticating.

# `token_to_resource`

```elixir
@spec token_to_resource(token(), module()) :: {:ok, Ash.Resource.t()} | :error
```

Given a token, find a matching resource configuration.

## Warning

This function *does not* validate the token, so don't rely on it for
authentication or authorisation.

# `verify`

```elixir
@spec verify(
  token(),
  Ash.Resource.t() | atom(),
  opts :: Keyword.t(),
  context :: map()
) ::
  {:ok, claims(), Ash.Resource.t()} | :error
```

Given a token, verify it's signature and validate it's claims.

---

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