MoneyHub.Auth.PrivateKeyJWT (MoneyHub v1.0.0)

Copy Markdown View Source

Builds and signs private_key_jwt client assertions.

Moneyhub's /oidc/token endpoint authenticates confidential clients via RFC 7523 private_key_jwt: instead of sending a client secret, the client signs a short-lived JWT with its own private key and presents that JWT as proof of identity.

This module builds that assertion (client_assertion) and is also used to sign request objects (the request parameter sent to /oidc/auth / /oidc/request and to payment/payee creation endpoints).

Loading a key

Moneyhub issues an RSA (or EC) private key when a client/software certificate is registered. Load it as a JOSE.JWK:

jwk = MoneyHub.Auth.PrivateKeyJWT.load_jwk!("priv/keys/client.pem")

or build one directly from PEM contents already in memory (e.g. from an environment variable or secrets manager):

jwk = MoneyHub.Auth.PrivateKeyJWT.jwk_from_pem!(pem_contents)

Summary

Functions

Builds a JOSE.JWK from PEM-encoded private key contents.

Loads a PEM-encoded private key from disk into a JOSE.JWK.

Signs an arbitrary claims map as a compact JWS using the given JWK.

Signs a private_key_jwt client assertion for the token endpoint.

Types

claims()

@type claims() :: %{optional(String.t()) => term()}

Functions

jwk_from_pem!(pem)

@spec jwk_from_pem!(String.t()) :: JOSE.JWK.t()

Builds a JOSE.JWK from PEM-encoded private key contents.

Raises MoneyHub.Error if the PEM cannot be parsed.

load_jwk!(path)

@spec load_jwk!(Path.t()) :: JOSE.JWK.t()

Loads a PEM-encoded private key from disk into a JOSE.JWK.

Raises MoneyHub.Error if the file cannot be read or parsed.

sign(jwk, kid, claims)

@spec sign(JOSE.JWK.t() | map(), String.t(), claims()) ::
  {:ok, String.t()} | {:error, MoneyHub.Error.t()}

Signs an arbitrary claims map as a compact JWS using the given JWK.

The signing algorithm is derived from the key type: RS256 for RSA keys, ES256 for EC P-256 keys. The kid is always embedded in the JWS header so Moneyhub can select the matching public key from your registered JWKS.

sign_client_assertion(config)

@spec sign_client_assertion(MoneyHub.Config.t()) ::
  {:ok, String.t()} | {:error, MoneyHub.Error.t()}

Signs a private_key_jwt client assertion for the token endpoint.

Per RFC 7523 / OIDC, the assertion asserts the client's own identity to itself as audience:

  • iss / sub - the client_id
  • aud - the token endpoint URL (identity_url <> "/oidc/token")
  • jti - a fresh unique identifier (replay protection)
  • iat / exp - issued-now, short expiry (60 seconds)

Returns the signed compact JWS as a string.