I have a bit of an #ActivityPub problem.
-
I have a bit of an #ActivityPub problem. I'm trying to implement an AP server that can send toots to #Mastodon. So far, I managed to follow a user on my server, that seems to work okay. However, when my server tries to send a Note, Mastodon accepts it, but it does not appear on the following user's timeline.
I'm not sure what I'm doing wrong. HTTP Signatures appear to be fine, because otherwise the follow wouldn't work either, and the Note Create activities wouldn't be accepted either.
For reference, here's how the user looks:
β― curl -s https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1 | jq .
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
],
"id": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1",
"type": "Person",
"name": "Gergely Nagy",
"icon": {
"type": "Image",
"mediaType": "image/png",
"url": "https://shoes.forgejo.madhouse-project.org/avatars/0eda2e83a694fb1986130c186f0339a049c9abe53dfc9e7c7bc7b3259c836c69"
},
"url": "https://shoes.forgejo.madhouse-project.org/algernon",
"inbox": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1/inbox",
"outbox": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1/outbox",
"preferredUsername": "algernon",
"publicKey": {
"id": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1#main-key",
"owner": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEApvsXapYe/P1naSa/0VW7\nHxLlCUjZGmMAm7jdjM5YOjVPd5WHC7yBj2rrJBMXnfT3dkDSdImIBVg7wB7QD//F\nJe9p4T5tzeERBOBdZ82BWsJsBB2ytSOq5UW1uE4YE4zEXutJcVW0tHhoS/vFQthV\nU4ayDMZf4pTlcwunjajgsWYMTr4uzYKd/nVvuDp9iIapQ/zZx/U2iPpCAkkR+mcT\nWIVCJNSai/S9gaN+AO2Wf0cTlW5qO6/tkJqozYSYXD7gVEAZaGMSgr4r6J5TiYL4\nqSyTbxRW1zYt9trCwi8+MVdKCbR349RKcbljnYl8Ge7uGckfIc+M3X5JAkhBxtWX\nT6eZbJVTgH4Z/0GSY4qw1goNkGk+3Rq84/dWJ2IJuJX6o6fScSQYWTWKub0rhU+m\nNM+Q0kDJ8XLMVEZuWFI9vN2KTxickwcCvCK7ck9vUZFNwXwQRLOKTGtJtH9zSJdJ\nEz8w6UlI43bvvnYndY+5NRgDCESuXw8yLDWp03wFmgDJAgMBAAE=\n-----END PUBLIC KEY-----\n"
}
}The activity I send out looks like this:
β― jq . <tmp/tootsie.json
{
"@context": "https://www.w3.org/ns/activitystreams",
"id": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1/activities/f8cdb5c8-5575-4eb9-b21c-9255bdb5a7de/activity",
"type": "Create",
"to": [
"https://www.w3.org/ns/activitystreams#Public"
],
"cc": [
"https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1/followers"
],
"published": "2024-08-02T16:54:59Z",
"actor": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1",
"object": {
"id": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1/activities/f8cdb5c8-5575-4eb9-b21c-9255bdb5a7de",
"type": "Note",
"content": "<a href=\"https://shoes.forgejo.madhouse-project.org/algernon\" rel=\"nofollow\">algernon</a> <a href=\"https://shoes.forgejo.madhouse-project.org/algernon/federation-test/issues/1#issuecomment-253\" rel=\"nofollow\">commented</a> on <a href=\"https://shoes.forgejo.madhouse-project.org/algernon/federation-test/issues/1\" rel=\"nofollow\">algernon/federation-test#1</a>: <blockquote><p dir=\"auto\">c</p>\n</blockquote>",
"attributedTo": "https://shoes.forgejo.madhouse-project.org/api/v1/activitypub/user-id/1",
"published": "2024-08-02T16:54:59Z"
}
}When sending this to Masto, with http signature, Masto replies with "202 Accepted". But the user I'm following with, does not see the note on the timeline.
Do I need to implement
outbox
? I'd prefer not to implementoutbox
if I can avoid it.If anyone wants to play with it, and perhaps help me debug what is going on, registrations on https://shoes.forgejo.madhouse-project.org/ are open. Creating a repo, opening an issue, and then commenting on that will all emit activities, which are sent to Masto as Notes.
-
@[email protected] are you sure it's the http signature?
If you're able to follow the user from Mastodon that means the Accept you sent was signed properly.
Therefore unless you're using a different code path, one can naΓ―vely assume that the signature for the post should also be ok.
Are you sure the Mastodon user is following? Not just requested?
-
@julian It's... complicated, I think!
Since my original toot, I can follow Forgejo accounts from GoToSocial, and from Mastodon instances that do not have
AUTHORIZED_FETCH
turned on.With
AUTHORIZED_FETCH
, when I try to retrieve the requester's key, Masto tells me I need to sign theHost
header too (Forgejo was only signingDate
and and the URI for GET requests). If I signHost
too, Mastodon fails to verify the signature.Mind you, this is during the follow process. Without
AUTHORIZED_FETCH
, everything works: follow & toot delivery both. With it, I have not managed to get past following yet. But I expect that whatever is the root cause, fixing it will make toot delivery work in theAUTHORIZED_FETCH
case too. -
@[email protected] in that case it sounds like the way you construct the Host header doesn't match how the Host header is constructed on the receiving end...
Perhaps inspecting how NodeBB does it may give you some insight?
-
@julian I should be doing it the same way, but... something goes off.
It verifies fine until I add the
host
header to the list, as long as the other end does not requirehost
. If I addhost
, both Masto and GtS fail to verify.Buuuut... I think I have an idea. At least a way to debug it further, now that I managed to trip GtS over too!
-
@[email protected] feels like you're close! It could be something dumb like you using your hostname instead of the recipient hostname.
-
@julian It's using the correct hostname, so it is going to be something even dumber. My current suspicion is
\r\n
vs\n
, but... then I'm gonna cry loudly. -
>Do I need to implement outbox? I'd prefer not to implement outbox if I can avoid it.
outbox
is required by standard, but it can be an empty collection -
@[email protected] but every time someone doesn't implement an inbox @[email protected] dies a little inside.