# `ExAwsSnsVerifier`
[🔗](https://github.com/GustavoZiaugra/ex_aws_sns_verifier/blob/v0.1.0/lib/ex_aws_sns_verifier.ex#L1)

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

# `t`

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

# `new`

```elixir
@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`

```elixir
@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!`

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

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

---

*Consult [api-reference.md](api-reference.md) for complete listing*
