Issue with Mastodon pulling posts & followers from new ActivityPub integration

Would like to thank all for the detailed input, particularly @nightpool.
It makes sense to proceed along the thread of getting “follows” working, then customize the application to POST new blog posts to the followers on Mastodon.

I have written the Express code to be able to parse the POST request which Mastodon sends upon a follow request, and extract both the relevant HTTP headers and request body:

HTTP Headers

headersToSign

(request-target): post /activitypub/test1234/inbox host: goaify.me date: Mon, 26 Aug 2024 17:04:14 GMT digest: SHA-256=byoTC4x/rKWnhg9+4XZeUDeesNVK17bbCSEdMm178F4= content-type: application/activity+json

signature

HQZW138MltJT/gSeUWj7PYQvY4xtBas9y1NxZ+p1Vph8UBr4LJOajwWfdc28bUiMOVYq9cWbQ29qy5zuLvAwujicbqnkX4s/iBb7m6sg2WFOMc/STv0/KncRQ8SqXV+2ZW64bZbVNgpy0CdPpjNhJO5oNAD5hFybTHx5IBhqm3TJttY5JyZEB4+R5vT1Q6L9fL4VaxjHv0RkA7fPM7PpbsrydibIeOZmHf7QtrL+5qWH+7C8eqKpmexEZ6j80/63KuH9zNrWe3tUastjOPPDO0s6LZOZnvJWMCkOQ1Pf7Tr772ZvEG2SDPDZXFwI4MW21s79PAqALTgGq5JLCeEP3Q==

HTTP Message Body

  • id https://mastodon.social/97ea7544-7d82-4ddf-9143-bc78bfa45ffe
  • type Follow
  • actor https://mastodon.social/users/jackie_liu
  • object https://goaify.me/activitypub/test1234

I also use Axios library and the Express JSON function to make a GET request to https://mastodon.social/users/mastodon_user#main-key to retrieve the publicKeyPem of the follower from the Mastodon server, and store it in a constant called publicKey.

publicKey

-----BEGIN PUBLIC KEY----- MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwyhIT8T0AftrbDhvil7L cCgzt0SVnUuONuk3lPTqwUCEJZYXIF88WLa6xFwQ2Pd19jT1kk3GbqDF86Kfy63t XFj8pTrgICvocaX5stLa64CU/L/K3fzpOktxYk53h2ujIfNm0V7AAF1y3ajQ/OIe LHHLOyXrrZxvPSEZWJigNK+bxNhszE09SnAyy39WlYuVpWRJQOvJjM7cusiHeqz+ 01ZBc9wTjZwgv0Vg924WJZqpuxvk8gg4Ecc/OWHIkpgEf3cieolJYb3sHbwo/HdH YR/NzWxzj7NE+AFk74qlJ4wLEqJfF5fKZCCBMTPYVwv0uKsJJVmPklHLnkWQQtRR NQIDAQAB -----END PUBLIC KEY-----

The headersToSign contains the parameters host, date, digest, content-type (outlined above) contained in the POST request that Mastodon makes to my ActivityPub instance as soon as the Follow request is made.

Edit: I’m able to verify the HTTP signature from Mastodon by converting the base64 encoded signature to a Buffer using the Buffer.from function and get a Signature verification succeeded in the console.

Here is the relevant code excerpt:

const crypto = require('crypto');

const remotePublicKeyPem = response.data.publicKey.publicKeyPem; 

    const publicKey = crypto.createPublicKey({
      key: remotePublicKeyPem,
      format: 'pem'
    });

    const verifier = crypto.createVerify('RSA-SHA256');
    verifier.update(headersToSign);
    verifier.end();

    const signatureBuffer = Buffer.from(signature, 'base64');

    if (publicKey !== undefined && signature !== undefined) {
      const isValid = verifier.verify(publicKey, signatureBuffer);

      if (!isValid) {
        console.log('Signature verification failed');
        return {
          error: "Signature verification failed"
        }
      }
      console.log('Signature verification succeeded');
    }

Next Steps

Next, I plan on writing the code which will allow the local ActivityPub account being followed to sign an Accept message using its own public key, and return that response to the Mastodon server. As well as update my /activitypub/test1234/followers route to read from a list of followers in a local database.