jose_utils v0.3.0 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

Link to this type

serialized()

View Source
serialized() :: String.t()

Serialized JWS signed token

For instance:

"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"

Link to this section Functions

Link to this function

peek_header(jws)

View Source
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"}}
Link to this function

sig_alg_type(jws)

View Source
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
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.

Notice that additional headers from the JWK or the additional_headers parameters are not serialized into the result JWS, because of lack of support by the underlying library.

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
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
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