Comparing server and client side generation of the HTTP signature header.
View the Project on GitHub cristianolongoodhl/clientsidehttpsignotes
Please contribute at the github repository cristianolongoodhl/clientsidehttpsignotes
As reported in the ActivityPub specification, an ActivityPub server must provide each Actor
with two ‘Collection’s: outbox
and inbox
. In addition, the addresses of these collections must be listed in the publicly available Actor
description.
Let us call target actors of an Activity
all the Actor
s to which the Activity
has to be delivered. Target actors of an activity are specified in the activity itself as described in the specification at 6.1 Client Addressing.
Now let use recall the Activity delivery process in ActivityPub.
Actor
has to place the activity into the outbox the server provided to her.Actor
may send to her server an Object
which cannot be recognized as an Activity
(see Note 1). This case must be handled by the server, as described in the specification at 6.2.1 Object creation without a Create Activity, with generating a novel Create
activity wrapping the object sent by the sender, and placing this novel activity in the outbox.Activity
has been placed into the sender outbox, the server sends it to the inbox
es of all the activity target actors. Notice that some of these inboxes may reside outside the sender server. In these cases we talk about a Server to Server communication, which is described in the specification at 7.1 Delivery.Notice that security mechanisms for both client-to-server and server-to-server communications are not specified in the protocol, as they are left to implementations. The ActivityPub specification refers (in a non-mandatory way) to the Social Web Community Group Authentication and Authorization best practices report, which effectively guided the most part of the ActivityPub implementations currently available.
For client to server communications, the report suggests OAuth 2, which is a well-established authentication and authorization protocol which, in addition, provides confidentiality features.
For server to server communications, the approach proposed by the report is to sign messages with HTTP Signatures as follows:
keyId
field of the Signature
header should link to the Actor
description which, in turn, must provide the public part of the actor key via a publicKey
property.Then, the receiving server can check message integrity with fetching the actor public key through keyId
and checking the message body (digest) against this public key.
This part of ActivityPub is quite controversial as in ActivityPub every Activity
is an Object
, so that one cannot deduce that an Object
is not an Activity
if not explicitly stated.
Some implementations such as, for example, Mastodon require to take into consideration also the date
header in the signature, in order to handle and eventually discard old messages which may be sent by malicious servers.
As reported in How to implement a basic ActivityPub server (see also Note 2) Mastodon servers defines a 30 seconds validity interval for messages. I.e., mastodon servers will discard messages received 30 seconds later the date reported in the date
header.
A mastodon servers acts as a key holder for users’ key pairs: key pairs of users are generated, stored and guarded by the server, which will use them to generate the signature header when delivering activities.
This approach has some advantages:
Accept
activity for follow requests;However, it has some relevant drawbacks:
Now, let us now consider a setup where the signature header is generated by the client. In such a setup, the outbox must receive from the client the date and the signature headers, aside with the activity to be sent. Then, the outbox forwards these headers, with in addition the activity digest and the activity itself, to the activity target inboxes.
Little ActivityPub Server is a proof of concept of such approach, as it provides a javascript-based form to generate the signature and send the required headers and the activity to an outbox.
Obviously, this approach does not require that the server knows client private keys. Instead, it shouldn’t so that [SD1] and [SD2] cannot hold anymore. More in details:
Aside these advantages, the approaches based on client-side generation has some relevant drawbacks.
One may argue that the server should sign outgoing activities using the key of its so called instance actor, i.e. an actor representing the whole server. This sounds even more appropriate in [CSO], as, in this case, the activity is not provided by the client but generated by the server itself.
In a discussion on the Semantic Web Community Group mailing list a security flow has been reported. However, in my opinion this flow does not concern if the signature is generated client-side or server side.
There are other approaches which should be taken into considerations, for example: