JOSEUtils.JWS (jose_utils v0.4.0) View Source

Convenience functions to work with signed JWTs

Link to this section Summary

Types

Serialized JWS signed token

Functions

Returns the unverified header

Returns :mac if the JWS uses a MAC signature algoithm, :public_key_crypto otherwise

Signs a payload with a JWK and a given signing algorithm

Verifies the signature of a JWS, and returns its content and the signature key

Link to this section Types

Specs

serialized() :: String.t()

Serialized JWS signed token

For instance:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

Link to this section Functions

Specs

peek_header(serialized()) ::
  {:ok, %{optional(String.t()) => any()}} | {:error, Exception.t()}

Returns the unverified header

It ensures the "alg" parameter is set.

Example

iex> JOSEUtils.JWS.peek_header("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.dMAojPMVbFvvkouYUSI9AxIRBxgqretQMCvNF7KmTHU")
{:ok, %{"alg" => "HS256", "typ" => "JWT"}}

iex> JOSEUtils.JWS.peek_header("probably invalid...?")
{:error, %JOSEUtils.JWS.MalformedError{message: "malformed JWS"}}

Specs

sig_alg_type(serialized()) :: :public_key_crypto | :mac

Returns :mac if the JWS uses a MAC signature algoithm, :public_key_crypto otherwise

Example

iex> JOSE.JWS.sign(JOSE.JWK.generate_key({:ec, "P-256"}), "toto", %{"alg" => "ES256"})
...> |> JOSE.JWS.compact()
...> |> elem(1)
...> |> JOSEUtils.JWS.sig_alg_type()
:public_key_crypto

iex> JOSE.JWS.sign(JOSE.JWK.generate_key({:oct, 32}), "toto", %{"alg" => "HS256"})
...> |> JOSE.JWS.compact()
...> |> elem(1)
...> |> JOSEUtils.JWS.sig_alg_type()
:mac
Link to this function

sign(payload, jwk, sig_alg, additional_headers \\ %{})

View Source

Specs

sign(
  payload :: any(),
  JOSEUtils.JWK.t() | any(),
  JOSEUtils.JWA.sig_alg(),
  additional_headers :: %{optional(String.t()) => any()}
) :: {:ok, serialized()} | {:error, Exception.t()}

Signs a payload with a JWK and a given signing algorithm

The payload can be a string, in which case it is signed directly, or any other data type which will first be converted into text using JSON serialization.

If the JWK has a key id ("kid" member), it is automatically added to the resulting JWS.

When using the "none" algorithm, anything can be passed as the JWK (as it is not used).

Example

iex> jwk = %{"k" => "FWTNVgrQyQyZmduoAVyOfI1myMs", "kty" => "oct"}
iex> JOSEUtils.JWS.sign("some text", jwk, "HS256")
{:ok, "eyJhbGciOiJIUzI1NiJ9.c29tZSB0ZXh0.2L2wNRpAOw92LSAII2PQ9_y9zi2YD9NfjJuGBpNkVBE"}

iex> JOSE.unsecured_signing(true)
iex> JOSEUtils.JWS.sign!("test payload", %{}, "none", %{"some" => "header"})
"eyJhbGciOiJub25lIiwic29tZSI6ImhlYWRlciJ9.dGVzdCBwYXlsb2Fk."
Link to this function

sign!(payload, jwk, sig_alg, additional_headers \\ %{})

View Source

Specs

sign!(
  payload :: any(),
  JOSEUtils.JWK.t(),
  JOSEUtils.JWA.sig_alg(),
  header :: %{optional(String.t()) => any()}
) :: serialized()

See sign/4

Link to this function

verify(jws, jwk, allowed_algs)

View Source

Specs

verify(
  jws :: serialized(),
  jwk_or_jwks :: JOSEUtils.JWK.t() | [JOSEUtils.JWK.t()],
  allowed_algs :: [JOSEUtils.JWA.sig_alg()]
) :: {:ok, {verified_content :: binary(), JOSEUtils.JWK.t()}} | :error

Verifies the signature of a JWS, and returns its content and the signature key

The function also filters the key using JOSEUtils.JWKS.verification_keys/2 with the whitelisted signature algorithms. If the JWS has an identifier ("kid"), it only uses that specific key.

Example

iex> JOSE.crypto_fallback(true)
iex> jwk_ed25519 = JOSE.JWK.generate_key({:okp, :Ed25519})
iex> jwk_ed25519_map = jwk_ed25519 |> JOSE.JWK.to_map() |> elem(1)
iex> signed_ed25519 = JOSE.JWS.sign(jwk_ed25519, "{}", %{ "alg" => "EdDSA" }) |> JOSE.JWS.compact |> elem(1)
iex> JOSEUtils.JWS.verify(signed_ed25519, jwk_ed25519_map, ["RS256"])
:error
iex> JOSEUtils.JWS.verify(signed_ed25519, jwk_ed25519_map, ["EdDSA"]) |> elem(0)
:ok