ExAwsSnsVerifier (ex_aws_sns_verifier v0.1.0)

Copy Markdown View Source

Verify the authenticity of AWS SNS HTTPS messages.

This is the Elixir equivalent of Ruby's Aws::SNS::MessageVerifier, filling a gap in the Elixir ecosystem. It verifies RSA-SHA256 (SignatureVersion 2) signatures on Notification, SubscriptionConfirmation, and UnsubscribeConfirmation payloads.

Usage

One-shot verification

raw_body = ~s({"Type": "Notification", ...})
opts = [allowed_topic_arns: ["arn:aws:sns:us-east-1:123456789012:MyTopic"]]

{:ok, payload} = ExAwsSnsVerifier.verify(raw_body, opts)
# or
payload = ExAwsSnsVerifier.verify!(raw_body, opts)

With Verifier struct (reused config)

verifier = ExAwsSnsVerifier.new(allowed_topic_arns: ["..."])
{:ok, payload} = ExAwsSnsVerifier.verify(verifier, raw_body)

Error reasons

On failure, verify/2 returns {:error, reason} where reason is one of:

:invalid_cert_url            SigningCertURL does not pass host validation
:topic_not_allowed           TopicArn not in allowed list
:unsupported_signature_version  Only SignatureVersion 2 (SHA256) supported
:type_header_mismatch        Message Type header does not match JSON
:timestamp_out_of_window     Message timestamp is outside the replay window
:missing_field               Required field is missing from message body
:signature_invalid           RSA-SHA256 signature does not verify
{:cert_fetch_failed, status}  HTTP error fetching signing cert
:invalid_subscribe_url       SubscribeURL fails host validation

Summary

Functions

Create a new ExAwsSnsVerifier struct with persistent configuration.

Verify the authenticity of a raw SNS message body.

Types

t()

@type t() :: %ExAwsSnsVerifier{
  allowed_regions: [String.t()],
  allowed_topic_arns: [String.t()],
  cert_cache: module(),
  http_client: module(),
  timestamp_window_seconds: pos_integer()
}

Functions

new(opts \\ [])

@spec new(keyword()) :: t()

Create a new ExAwsSnsVerifier struct with persistent configuration.

Options

  • :allowed_topic_arns — list of allowed TopicArn values (required)
  • :allowed_regions — list of AWS regions for SigningCertURL validation (defaults to all commercial regions)
  • :timestamp_window_seconds — replay window in seconds (default: 3600)
  • :http_client — module implementing get/1 for cert fetching (default: ExAwsSnsVerifier.Cert.HttpClient, which uses :httpc)
  • :cert_cache — module implementing get/1 and put/2 for cert caching (default: ExAwsSnsVerifier.Cert.Cache using :persistent_term)

verify(verifier_or_body, opts_or_body \\ [])

@spec verify(String.t() | t(), keyword() | String.t()) ::
  {:ok, map()} | {:error, atom()}

Verify the authenticity of a raw SNS message body.

Returns {:ok, decoded_payload} on success or {:error, reason} on failure.

verify!(verifier_or_body, opts_or_body \\ [])

@spec verify!(String.t() | t(), keyword() | String.t()) :: map()

Same as verify/2 but raises ExAwsSnsVerifier.VerificationError on failure.