Add digest, date and request-target in HTTP signature
This commit is contained in:
parent
26d57b6273
commit
fc226f6c68
@ -15,6 +15,7 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
|
|
||||||
alias Mobilizon.Service.Federator
|
alias Mobilizon.Service.Federator
|
||||||
|
alias Mobilizon.Service.HTTPSignatures
|
||||||
|
|
||||||
require Logger
|
require Logger
|
||||||
import Mobilizon.Service.ActivityPub.Utils
|
import Mobilizon.Service.ActivityPub.Utils
|
||||||
@ -277,23 +278,35 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
|
|
||||||
def publish_one(%{inbox: inbox, json: json, actor: actor, id: id}) do
|
def publish_one(%{inbox: inbox, json: json, actor: actor, id: id}) do
|
||||||
Logger.info("Federating #{id} to #{inbox}")
|
Logger.info("Federating #{id} to #{inbox}")
|
||||||
host = URI.parse(inbox).host
|
{host, path} = URI.parse(inbox)
|
||||||
|
|
||||||
|
digest = HTTPSignatures.build_digest(json)
|
||||||
|
date = HTTPSignatures.generate_date_header()
|
||||||
|
request_target = HTTPSignatures.generate_request_target("POST", path)
|
||||||
|
|
||||||
signature =
|
signature =
|
||||||
Mobilizon.Service.HTTPSignatures.sign(actor, %{
|
HTTPSignatures.sign(actor, %{
|
||||||
host: host,
|
host: host,
|
||||||
"content-length": byte_size(json)
|
"content-length": byte_size(json),
|
||||||
|
"(request-target)": request_target,
|
||||||
|
digest: digest,
|
||||||
|
date: date
|
||||||
})
|
})
|
||||||
|
|
||||||
HTTPoison.post(
|
HTTPoison.post(
|
||||||
inbox,
|
inbox,
|
||||||
json,
|
json,
|
||||||
[{"Content-Type", "application/activity+json"}, {"signature", signature}],
|
[
|
||||||
|
{"Content-Type", "application/activity+json"},
|
||||||
|
{"signature", signature},
|
||||||
|
{"digest", digest},
|
||||||
|
{"date", date}
|
||||||
|
],
|
||||||
hackney: [pool: :default]
|
hackney: [pool: :default]
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Fetching a remote actor's informations through it's AP ID
|
# Fetching a remote actor's informations through it's AP ID
|
||||||
@spec fetch_and_prepare_actor_from_url(String.t()) :: {:ok, struct()} | {:error, atom()} | any()
|
@spec fetch_and_prepare_actor_from_url(String.t()) :: {:ok, struct()} | {:error, atom()} | any()
|
||||||
defp fetch_and_prepare_actor_from_url(url) do
|
defp fetch_and_prepare_actor_from_url(url) do
|
||||||
Logger.debug("Fetching and preparing actor from url")
|
Logger.debug("Fetching and preparing actor from url")
|
||||||
|
@ -94,6 +94,24 @@ defmodule Mobilizon.Service.HTTPSignatures do
|
|||||||
err ->
|
err ->
|
||||||
Logger.error("Unable to sign headers")
|
Logger.error("Unable to sign headers")
|
||||||
Logger.error(inspect(err))
|
Logger.error(inspect(err))
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def generate_date_header(date \\ Timex.now("GMT")) do
|
||||||
|
with {:ok, date} <- Timex.format(date, "%a, %d %b %Y %H:%M:%S %Z", :strftime) do
|
||||||
|
date
|
||||||
|
else
|
||||||
|
{:error, err} ->
|
||||||
|
Logger.error("Unable to generate date header")
|
||||||
|
Logger.error(inspect(err))
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def generate_request_target(method, path), do: "#{method} #{path}"
|
||||||
|
|
||||||
|
def build_digest(body) do
|
||||||
|
"SHA-256=" <> (:crypto.hash(:sha256, body) |> Base.encode64())
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
2
mix.exs
2
mix.exs
@ -35,7 +35,7 @@ defmodule Mobilizon.Mixfile do
|
|||||||
def application do
|
def application do
|
||||||
[
|
[
|
||||||
mod: {Mobilizon.Application, []},
|
mod: {Mobilizon.Application, []},
|
||||||
extra_applications: [:logger, :runtime_tools, :guardian, :bamboo, :geolix]
|
extra_applications: [:logger, :runtime_tools, :guardian, :bamboo, :geolix, :crypto]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ defmodule Mobilizon.Service.Activitypub.ActivitypubTest do
|
|||||||
alias Mobilizon.Events
|
alias Mobilizon.Events
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Actors
|
alias Mobilizon.Actors
|
||||||
|
alias Mobilizon.Service.HTTPSignatures
|
||||||
alias Mobilizon.Service.ActivityPub
|
alias Mobilizon.Service.ActivityPub
|
||||||
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
||||||
|
|
||||||
@ -13,6 +14,23 @@ defmodule Mobilizon.Service.Activitypub.ActivitypubTest do
|
|||||||
HTTPoison.start()
|
HTTPoison.start()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "setting HTTP signature" do
|
||||||
|
test "set http signature header" do
|
||||||
|
actor = insert(:actor)
|
||||||
|
|
||||||
|
signature =
|
||||||
|
HTTPSignatures.sign(actor, %{
|
||||||
|
host: "example.com",
|
||||||
|
"content-length": 15,
|
||||||
|
digest: Jason.encode!(%{id: "my_id"}) |> HTTPSignatures.build_digest(),
|
||||||
|
"(request-target)": HTTPSignatures.generate_request_target("POST", "/inbox"),
|
||||||
|
date: HTTPSignatures.generate_date_header()
|
||||||
|
})
|
||||||
|
|
||||||
|
assert signature =~ "headers=\"(request-target) content-length date digest host\""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "fetching actor from it's url" do
|
describe "fetching actor from it's url" do
|
||||||
test "returns an actor from nickname" do
|
test "returns an actor from nickname" do
|
||||||
use_cassette "activity_pub/fetch_tcit@framapiaf.org" do
|
use_cassette "activity_pub/fetch_tcit@framapiaf.org" do
|
||||||
|
Loading…
Reference in New Issue
Block a user