A compliant and complete implementation of PASETO and PASERK.
PASETO is everything you love about JOSE (JWT, JWE, JWS) without any of the many design deficits that plague the JOSE standards.
PASETO (Platform-Agnostic SEcurity TOkens) is a specification and reference implementation for secure stateless tokens.
Paseto is pronounced paw-set-oh (pɔːsɛtəʊ).
Key Differences between Paseto and JWT
Unlike JSON Web Tokens (JWT), which gives developers more than enough rope with which to hang themselves, PASETO only allows secure operations. JWT gives you "algorithm agility", PASETO gives you "versioned protocols". It's incredibly unlikely that you'll be able to use Paseto in an insecure way.
Caution: Neither JWT nor PASETO were designed for stateless session management. Paseto is suitable for tamper-proof cookies, but cannot prevent replay attacks by itself.
PASETO
PASETO expects a version and a purpose in order to build and parse tokens. The version is a string that represents the current version of the protocol. The purpose is a short string describing the purpose of the token, where the accepted values are:
local: shared-key authenticated encryption
public: public-key digital signatures; not encrypted
Tokens can be built and parsed like so:
iex> key = Pasexto.Key.new(:v4, :local)
iex> claims = %{"hello" => "world"}
iex> footer = <<>>
iex> {:ok, paseto, claims} = Pasexto.build(:v4, :local, key, claims, footer)
iex> {:ok, ^claims, ^footer} = Pasexto.parse(:v4, :local, key, paseto)
iex> key = Pasexto.Key.new(:v4, :public)
iex> claims = %{"hello" => "world"}
iex> footer = <<>>
iex> {:ok, paseto, claims} = Pasexto.build(:v4, :public, key, claims, footer)
iex> {:ok, ^claims, ^footer} = Pasexto.parse(:v4, :public, key, paseto)Keyring
This library also supports keyrings making it easier to manage a group of keys. It can be used like so:
iex> key = Pasexto.Key.new(:v4, :local)
iex> keyring = Pasexto.Keyring.new(:v4, :local) |> Pasexto.Keyring.put("key1", key)
iex> claims = %{"hello" => "world"}
iex> footer = %{"kid" => "key1"}
iex> {:ok, paseto, claims} = Pasexto.build(:v4, :local, keyring, claims, footer)
iex> {:ok, ^claims, ^footer} = Pasexto.parse(:v4, :local, keyring, paseto)PASERK
PASERK is an extension to PASETO that provides key-wrapping and serialization. It can be used like so:
iex> key = Pasexto.Key.new(:v4, :local)
iex> {:ok, kid} = Pasexto.Paserk.build(:k4, :lid, key)
iex> keyring = Pasexto.Keyring.new(:v4, :local) |> Pasexto.Keyring.put(kid, key)
iex> claims = %{"hello" => "world"}
iex> footer = %{"kid" => kid}
iex> {:ok, paseto, claims} = Pasexto.build(:v4, :local, keyring, claims, footer)
iex> {:ok, ^claims, ^footer} = Pasexto.parse(:v4, :local, keyring, paseto)
Summary
Functions
Builds a PASETO token for the given version and purpose.
Parses a PASETO token for the given version and purpose.
Peek at the footer of a token.
Types
Functions
@spec build( version(), purpose(), Pasexto.Key.t() | Pasexto.Keyring.t(), map(), binary() | map(), keyword() ) :: {:ok, binary(), map()} | {:error, term()}
Builds a PASETO token for the given version and purpose.
The key must be a Key.t() or Keyring.t() and it must match the given
version and purpose. When a keyring is provided the footer must be a map and
must contain a kid for a key within the keyring.
Options
defaults- Default claims to merge into the provided claims, it expects a keyword list where the value can be a static value or a function that takes no arguments, defaults tonil. Ifnilthen the following claims are applied:[ exp: fn -> DateTime.utc_now(:second) |> DateTime.shift(hour: 1) |> DateTime.to_iso8601() end, iat: fn -> DateTime.utc_now(:second) |> DateTime.to_iso8601() end, nbf: fn -> DateTime.utc_now(:second) |> DateTime.to_iso8601() end, jti: fn -> :crypto.strong_rand_bytes(16) |> Base.hex_encode32(case: :lower, padding: false) end ]deprecated- Allows the usage of deprecated versions, defaults tofalse.implicits- A map or binary of assertions to bind to the token without being included, defaults tonil.rules- A collection of rules to verify the claims within a token, defaults tonil. Ifnilthen the following rules are applied:[ &Pasexto.Rules.validate_required(&1), &Pasexto.Rules.validate_exp(&1), &Pasexto.Rules.validate_iat(&1), &Pasexto.Rules.validate_nbf(&1) ]
@spec parse( version(), purpose(), Pasexto.Key.t() | Pasexto.Keyring.t(), binary(), keyword() ) :: {:ok, map(), binary() | map()} | {:error, term()}
Parses a PASETO token for the given version and purpose.
Upon success it returns the claims and footer contained within the token.
The key must be a Key.t() or Keyring.t() and it must match the given
version and purpose. When a keyring is provided the footer is checked to see
if it contains a valid kid used to lookup the key within the keyring.
Options
deprecated- Allows the usage of deprecated versions, defaults tofalse.implicits- A map or binary of assertions expected to have been bound to the token, defaults tonil.max_depth- The maximum level of nesting allowed within a JSON footer object, defaults to1.max_keys- The maximum number of keys allowed within a JSON footer object, defaults to10.rules- A collection of rules to verify the claims within a token, defaults tonil. Ifnilthen the following rules are applied:[ &Pasexto.Rules.validate_required(&1), &Pasexto.Rules.validate_exp(&1), &Pasexto.Rules.validate_iat(&1), &Pasexto.Rules.validate_nbf(&1) ]
Peek at the footer of a token.
Options
deprecated- Allows the usage of deprecated versions, defaults tofalse.max_depth- The maximum level of nesting allowed within a JSON footer object, defaults to1.max_keys- The maximum number of keys allowed within a JSON footer object, defaults to10.