Skip to content
Verify signed HTTP requests from Manifold in Elixir
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
config
lib
test
.formatter.exs
.gitignore
CHANGELOG.md
LICENSE.md
README.md
mix.exs
mix.lock

README.md

ManifoldcoSignature

Verify signed HTTP requests from Manifold.

Installation

If available in Hex, the package can be installed by adding manifoldco_signature to your list of dependencies in mix.exs:

def deps do
  [
    # Required for the `manifoldco_signature` dependency.
    {:enacl, github: "jlouis/enacl", ref: "c8403ab198b80863479c2ab5a9ccd0a8d73a57c4"}
    {:manifoldco_signature, "~> 0.0.1"}
  ]
end

Note that this library uses a specific version of the enacl library. This is due to broken build requirements when trying to compile the libsodium bindings.

Oh, and you'll need libsodium to be installed on the host machine. If you're on mac you can do so via:

brew install libsodium

Documentation

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/manifoldco_signature.

Using with Plug

This library does not include Plug as a dependency but instead takes the raw request arguments so that you can use your framework of choise. Since Plug is popular below is a plug that works with this library:

defmodule ManifoldAuthorization do
  @moduledoc """
  Plug that authenicates requests from the Manifold.co service.
  """

  alias ManifoldcoSignature

  require Logger

  @behaviour Plug

  #
  # Callbacks
  #

  def init(_opts) do
    []
  end

  def call(conn, _opts) do
    conn = Plug.Conn.fetch_query_params(conn)
    method = conn.method
    request_path = conn.request_path
    query_string = conn.query_string
    headers = conn.req_headers

    with {:ok, body, conn} <- Plug.Conn.read_body(conn),
         :ok <- ManifoldcoSignature.verify(method, request_path, query_string, headers, body),
         # We must parse the body here because `Plug.Conn.read_body/1` can only be called once.
         # Once called the body is no longer available.
         {:ok, body_params} <- Poison.decode(body) do
      Map.put(conn, :body_params, body_params)
    else
      {:error, reason} ->
        Logger.info(fn ->
          "Manifold authentication failed: #{inspect(reason)}"
        end)

        conn
        |> Plug.Conn.send_resp(:unauthorized, "")
        |> Plug.Conn.halt()
    end
  end
end

Warning

You must remove the Plug.Parsers plug in your endpoint.ex file since it reads the body, this makes it impossibel for the above manifold plug to read the body also.

Credit

This package was built by

timber.io

A Manifold logging provider.

You can’t perform that action at this time.