jose_utils v0.3.2 JOSEUtils.JWS 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(),
  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.

Example

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