<commit_before>## Joken [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/joken/) [![Downloads](https://img.shields.io/hexpm/dt/joken.svg)](https://hex.pm/packages/joken)


Encodes and decodes JSON Web Tokens.

Currently supports the following algorithms:

* HS256
* HS384
* HS512

Currently supports the following claims:

* Expiration (exp)
* Not Before (nbf)
* Audience (aud)
* Issuer (iss)
* Subject (sub)
* Issued At (iat)
* JSON Token ID (jti)


Usage:

  First, create a module that implements the `Joken.Config` Behaviour. 
  This Behaviour is responsible for the following:

    * encoding and decoding tokens
    * adding and validating claims
    * secret key used for encoding and decoding
    * the algorithm used

  If a claim function returns `nil` then that claim will not be added to the token. 
  Here is a full example of a module that would add and validate the `exp` claim 
  and not add or validate the others:

```elixir
  defmodule My.Config.Module do
    @behaviour Joken.Config

    def secret_key() do
      Application.get_env(:app, :secret_key)
    end

    def algorithm() do
      :HS256
    end

    def encode(map) do
      Poison.encode!(map)
    end

    def decode(binary) do
      Poison.decode!(binary)
    end

    def claim(:exp, payload) do
      Joken.Helpers.get_current_time() + 300
    end

    def claim(_, _) do
      nil
    end

    def validate_claim(:exp, payload, options) do
      Joken.Helpers.validate_time_claim(payload, "exp", "Token expired", fn(expires_at, now) -> expires_at > now end)
    end

    def validate_claim(_, _, _) do
      :ok
    end
  end
```


Joken looks for a `joken` config with `config_module`. `config_module` module being a module that implements the `Joken.Config` Behaviour.


```elixir
     config :joken,
       config_module: My.Config.Module
```

then to encode and decode

```elixir
{:ok, token} = Joken.encode(%{username: "johndoe"})

{:ok, decoded_payload} = Joken.decode(jwt)
```
<commit_msg>Enhanced README's USAGE and tidied it up<commit_after>## Joken [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/joken/) [![Downloads](https://img.shields.io/hexpm/dt/joken.svg)](https://hex.pm/packages/joken)


Encodes and decodes JSON Web Tokens.

Currently supports the following algorithms:

* HS256
* HS384
* HS512

Currently supports the following claims:

* **exp**: Expiration
* **nbf**: Not Before
* **aud**: Audience
* **iss**: Issuer
* **sub**: Subject
* **iat**: Issued At
* **jti**: JSON Token ID

For a more in depth description of each claim, please see the reference specification draft [here](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html).

### Usage:

Joken only needs an implementation of the `Joken.Config` behaviour to work properly. There is where you tell Joken:

* the chosen cryptographic algorithm (i.e.: HS256)
* the secret used to encode and to verify the payload
* how should it encode and decode JSON (i.e.: using Poison.encode!)
* which custom claims it should add
* how to validate all claims

To do that, you must implement the following callbacks:

* `secret_key` -> should return the key used to encrypt tokens. Remember that if you issue tokens using a secret, you can only verify them with the same secret, so this secret must be a constant and persistent value! Also, it seems obvious but does not hurt to mention: this should be a secret value. If it is somehow stolen it will be possible to create tokens that will pass your signing verification process.
* `algorithm` -> return one of the supported algorithms
* `encode(map_or_struct)` -> how Joken will encode claims into JSON
* `decode(binary)` -> how Joken will decode binaries into a valid structure
* `claim(claim, payload)` -> for adding claims to a token. If it returns `nil` then that claim will not be added to the token.
* `validate_claim(claim, payload, options)` -> the logic to validate a specific claim.
 
Here is a full example of a module that would add and validate the `exp` claim 
and not add or validate the others:

```elixir
  defmodule My.Config.Module do
    @behaviour Joken.Config

    def secret_key(), do: Application.get_env(:app, :secret_key) 
    
    def algorithm(), do: :HS256
    
    def encode(map), do: Poison.encode!(map)
    
    def decode(binary), do: Poison.decode!(binary)

    def claim(:exp, payload) do
      Joken.Helpers.get_current_time() + 300
    end

    def claim(_, _), do: nil

    def validate_claim(:exp, payload, options) do
      Joken.Helpers.validate_time_claim(payload, "exp", "Token expired", fn(expires_at, now) -> expires_at > now end)
    end

    def validate_claim(_, _, _), do: :ok
  end
```

Once you have implemented the behaviour module, you must add a configuration for `joken` with a property `config_module` with your behaviour module. Ex:

```elixir
config :joken,
  config_module: My.Config.Module
```

then to encode:

```elixir
{:ok, token} = Joken.encode(%{username: "johndoe"})
```

and to decode:
```elixir
{:ok, decoded_payload} = Joken.decode(jwt)
```

{'fraction_non_alphanumeric': 0.11063246524378305, 'fraction_numerical': 0.006461719208928921, 'mean_word_length': 3.76937441643324, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1286989', 'n_tokens_mistral': 1659, 'n_tokens_neox': 1558, 'n_words': 588}