Limen.Challenge.Token (limen v0.2.1)

Copy Markdown View Source

Stateless, signed challenge tokens.

A token carries a version, the difficulty, when it was issued and when it expires, and a random salt, followed by a truncated HMAC-SHA256 over those fields and the client identity (see Limen.Challenge.binding/1). The identity is not stored in the token, so a token solved by one client is useless to any other.

<<version, difficulty, issued_at::32, expires_at::32, salt::8 bytes, mac::16 bytes>>

It is sent URL-safe base64 encoded, 46 characters.

Summary

Functions

Issues a token for the client in ctx.

Whether nonce solves token at difficulty: SHA-256(token <> nonce) starts with at least difficulty zero bits.

Verifies a token presented by the client in ctx.

Types

claims()

@type claims() :: %{
  difficulty: pos_integer(),
  issued_at: non_neg_integer(),
  expires_at: non_neg_integer(),
  mac: binary()
}

Functions

issue(ctx, difficulty)

@spec issue(Limen.Context.t(), pos_integer()) :: String.t()

Issues a token for the client in ctx.

solved?(token, nonce, difficulty)

@spec solved?(String.t(), String.t(), pos_integer()) :: boolean()

Whether nonce solves token at difficulty: SHA-256(token <> nonce) starts with at least difficulty zero bits.

Nonces are decimal strings of at most 20 digits.

verify(token, ctx)

@spec verify(String.t(), Limen.Context.t()) ::
  {:ok, claims()} | {:error, :malformed | :invalid | :expired}

Verifies a token presented by the client in ctx.