Current section

Files

Jump to
messenger_bot lib messenger_bot plugs authenticate.ex
Raw

lib/messenger_bot/plugs/authenticate.ex

defmodule MessengerBot.Plug.Authenticate do
@moduledoc """
MessengerBot plug implementation to verify the sha1 signature with request body.
"""
import Plug.Conn
alias Plug.Conn
alias MessengerBot.Config
alias :crypto, as: Crypto
@doc false
def init(opts) do
opts
end
@doc false
def call(%{method: "POST"} = conn, _opts) do
{:ok, body, _} = Conn.read_body(conn)
conn = put_private(conn, :body, body)
case Conn.get_req_header(conn, "x-hub-signature") do
["sha1=" <> signature] ->
expected_signature = calculate_request_signature(body)
case signature == expected_signature do
true -> conn
false -> err_resp(conn, :unauthorized, %{"signature" => "invalid"})
end
_ ->
err_resp(conn, :unauthorized, %{"signature" => "required"})
end
end
def call(conn, _),
do: conn
defp calculate_request_signature(body) do
:sha
|> Crypto.hmac(Config.app_token(), body)
|> Base.encode16()
|> String.downcase()
end
defp err_resp(conn, status, errors) do
conn
|> put_resp_content_type("application/json")
|> send_resp(status, :jiffy.encode(%{errors: errors}))
|> halt()
end
end