Add an Instance Actor to allow for federation with Mastodon in secure mode
Problem
Mobilizòn cannot accept follow requests from a Mastodon instance configured in secure mode.
Cause
This is because of a chicken-egg situation with signature verification. When a Mastodon instance sends a follow request to a Mobilizòn instance this request is signed, and the signature must be verified. So Mobilizòn sends a request for the actor object to get the actor's public key for signature validation. Mobilizòn does not sign this request in lib/federation/http_signatures/signature.ex :
# Gets a public key for a given ActivityPub actor ID (url).
@spec get_public_key_for_url(String.t()) ::
{:ok, String.t()}
| {:error, :actor_not_found | :pem_decode_error}
defp get_public_key_for_url(url) do
with {:ok, %Actor{} = actor} <-
ActivityPubActor.get_or_fetch_actor_by_url(url, ignore_sign_object_fetches: true) do
get_actor_public_key(actor)
end
end
This is intentional per this comment in the similar refetch_public_key function:
# In this specific case we don't sign object fetches because
# this would cause infinite recursion when servers both need
# to fetch each other's keys
However, if the Mastodon server is in secure mode it will not accept the request for the user object unless it is signed.
Proposed Solution
Mastodon itself works around this by using an instance actor to sign this sort of request, rather than leaving them unsigned. I've looked around the code, and have done some web-fingering, but it appears that Mobilizòn does not have such an instance actor.
It might be possible to substitute the relay actor, but that's not entirely clear to me yet.
So for now at least I'd like to propose that we add an instance actor, like the one in Mastodon, and that it be used to sign what are now intentionally unsigned requests.