BIN-2 Moo Client Registration Flow
In this second _Bovine Implementation Note, I introduce a flow how to register ActivityPub Clients with an ActivityPub Server based on Moo-Auth-1. The goal here is to describe behavior that is already implemented in bovine and used for example in mechanical_bull. By the use of asymmetric encryption (Ed25519), there is no need for a secret to be exchanged in order to register a client.
Preliminaries
To simplify the description, I will focus on the simplest case:
- We have a User. Let’s call her Alice.
- Alice has an ActivityPub Actor
https://abel/actors/alice
managed on the ActivityPub Server Abel. - Alice wants to use the ActivityPub Client Banach, that she has installed on her computer.
We will furthermore assume that there exists a management interface on Abel that Alice can use to manage her account. What we need from the management interace is essentially something like the provideClientKey
method described in the ActivityPub Spec. However, it can be implemented entirely differently and not be part of the actor object, e.g. through a management HTML page.
In the above picture, the ActivityPub Client and Server form the bridge between Alice and her Actor. From this view point, it would be the Actor and not the ActivityPub Server that is sending messages to other Actors.
The Moo Client Registration Flow
The following 3 steps to describe the Moo Client Registration Flow from Alice‘s perspective.
Step 1: Alice starts Banach
Upon starting Banach, Alice is prompted to enter the domain of her server, i.e. abel
. Then Banach generates a new random Ed25519 private key, e.g. in multibase/codec encoding
z3u2Yxcowsarethebestcowsarethebestcowsarethebest
and displays the corresponding did-key to Alice while prompting her to add it to the authorized public keys for her actor. Example did-key:
did:key:z6MkekwC6R9bj9ErToB7AiZJfyCSDhaZe1UxhDbCqJrhqpS5
Step 2: Alice adds the did-key
Alice now opens her management interface on Abel and adds the did-key there.
Step 3: Alice tells Banach to proceed
For example, Alice presses enter. Banach then starts doing stuff, first he looks up the did-key on Abel via webfinger, i.e.
GET https://abel/.well-known/webfinger?resource=did:key:z6MkekwC6R9bj9ErToB7AiZJfyCSDhaZe1UxhDbCqJrhqpS5
The returned information is then expected to contain a reference to Alice‘s actor, e.g.
{
"href": "https://abel/actors/alice",
"rel": "self",
"type": "application/activity+json",
}
With this information Banach is now able to access Alice‘s actor and discover all relevant urls to do ActivityPub. As Banach is using Moo-Auth-1 to sign its messages to Abel, no further configuration is necessary.
Further Comments
One might consider including a mechanism in all this to rotate the keys Banach is using. This is not terribly hard to implement, I’m just unsure who should trigger a key rotation: Alice? Banach? Abel? Finally, as the secret key never leaves Banach, I’m unsure how necessary key rotation actually is.
In order to further simplify the flow, one could add another endpoint to Abel, where the logged in user can register the key. This means Alice would open
https://abel/registerPublicKey?key=did:key:z6MkekwC6R9bj9ErToB7AiZJfyCSDhaZe1UxhDbCqJrhqpS5
I want to collect more experience, before implementing something like this.
I often hear OAuth2 mentioned when people talk about Authorization between ActivityPub Client and Server. Unfortunately, I’m not aware of any implementations, so it is hard to compare this to it. With the above inclusion of the new endpoint, this flow can be reduced to entering a hostname and clicking a link, I’m unsure if one is able to achieve this with OAuth2 and if how.
If server is in charge of key rotation, you can probably use https://w3c-ccg.github.io/did-method-web/
Changing the did-key of a client regularly is probably somewhat abusive of the did concept. That's why I'm leaving this as an issue to think about.
https://www.w3.org/TR/did-core/#persistence
I read it as a recommendation to use DIDs as persistent identifiers, while keeping in mind that things sometimes not go as planned.