Follow Activity python code not working, STUCK!

Hi all,
I am trying to wrote some sample Follow code and Instance response code on the Fediverse, but am not having success after a prolonged period of time.

In short, I am trying to simulate a Follow request from one instance to another. The Follow Request instance is supposed to be farhan@p.farhan.codes. This runs some custom Python code I have written. The receiving host is ngrok@ee880c3b32b8.ngrok.io, an active instance running Pleroma.

I am having the receiving host, in this case ee880c3b32b8 (dot) ngrok (dot) io (changed because of forum limitations), reach back out to the test server, p.farhan.codes/users/farhan, upon which it reports back that there was a failure.

I suspect the mistake is somewhere in the httpsig or the response, but I have no idea where or what. My follow code is as follows below. Feel free to also reach out to the running host p.farhan.codes.

Please please assist! I am utterly stuck!
https://dpaste.org/8OGk

I don’t see where you’re making the actor object available when the receiving host tries to request it. See this tutorial and its second part.

1 Like

Hi Grishka,

I did not understand what you mean by not making the actor object available. Do you mean that the Requested instance, in this case ee880c3b32b8(dot)ngrok(dot)io, will reach back out to the requestor instance? Would that be a request to /inbox/username? I have code that does exactly that and replies with the public portion of the certificate used to send the initial certificate. However, I still receive an “error” message.

My thoughts are either:
A. The format that it is replying in is not correct - However, I verbatim copied a Mastodon instance’s reply format.
B. Something is wrong with the HTTP sig code
C. Something else.

I read the Mastodon documentation, but to be honest, it is not very clear on how a response to the actor object should look.

Still stuck and don’t have a path forward…

It will request the actor object from the URL you specify in the actor field in your activity. The object should be a well-formed JSON document, with the public key among other things. Please read the tutorials I linked, they explain everything you need to achieve the exact thing you’re trying to do. Just replace Ruby code with Python equivalent.

Your publicKeyPem is not being encoded correctly. When I run

curl https://p.farhan.codes/users/farhan -H "Accept: application/activity+json"

I get:

{
  "@context": ["https://www.w3.org/ns/activitystreams", "https://p.farhan.codes/schemas/litepub-0.1.jsonld", {"@language": "und"}],
  "attachment": [],
  "capabilities": {"acceptsChatMessages": true},
  "discoverable": false,
  "endpoints": {"oauthAuthorizationEndpoint": "https://p.farhan.codes/oauth/authorize", "oauthRegistrationEndpoint": "https://p.farhan.codes/api/v1/apps", "oauthTokenEndpoint": "https://p.farhan.codes/oauth/token", "sharedInbox": "https://p.farhan.codes/inbox", "uploadMedia": "https://p.farhan.codes/api/ap/upload_media"},
  "followers": "https://p.farhan.codes/users/farhan/followers",
  "following": "https://p.farhan.codes/users/farhan/following",
  "id": "https://p.farhan.codes/users/farhan",
  "inbox": "https://p.farhan.codes/users/farhan/inbox",
  "manuallyApprovesFollowers": false,
  "name": "farhan",
  "outbox": "https://p.farhan.codes/users/farhan/outbox",
  "preferredUsername": "farhan",
  "publicKey": {
    "id": "https://p.farhan.codes/users/farhan#main-key",
    "owner": "https://p.farhan.codes/users/farhan",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn5JI+uBbt3w0tPekK+UD\\naQLRG220XztYLEE1gC8eGYctYgrTX0wruNP+CFap1VsvyWxRoitNjFLDD3pwYxK9\\n+k6P459ekL0fSRqQ0bzOQ5Vb22PBs9iOKonV9FSljCcDg0kc3cvxCeU246BMurGI\\nIs0vWk3UwygkeMo+rYXDluTtuSvZs+2ume2JYgrtcQoDH5YzU+76dRLYfd1+xEFo\\nP+K0hFb7+LhwGwDuLtTUYQ39kqm2jnC9/3W5yyweBqh05iQ0joDC0nuoZpjvT7on\\n2Obwluci30Q2xS1i+5244qr9Ouq1EK+9kdf15RMMOH1Azumho1YNFoVZlcxy2bar\\n6wIDAQAB\\n-----END PUBLIC KEY-----\\n"
  },
  "summary": "",
  "tag": [], "type":
  "Person",
  "url": "https://p.farhan.codes/users/farhan"
}

Which has publicKeyPem improperly escaped with \\n instead of \n. For verification, see this playground in Golang.

2 Likes

I modified the code to remove the double escape characters. The failure remains. Please see below:

$ curl https://p.farhan.codes/users/farhan -H "Accept: application/activity+json"
{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    "https://p.farhan.codes/schemas/litepub-0.1.jsonld",
    {
      "@language": "und"
    }
  ],
  "attachment": [],
  "capabilities": {
    "acceptsChatMessages": true
  },
  "discoverable": false,
  "endpoints": {
    "oauthAuthorizationEndpoint": "https://p.farhan.codes/oauth/authorize",
    "oauthRegistrationEndpoint": "https://p.farhan.codes/api/v1/apps",
    "oauthTokenEndpoint": "https://p.farhan.codes/oauth/token",
    "sharedInbox": "https://p.farhan.codes/inbox",
    "uploadMedia": "https://p.farhan.codes/api/ap/upload_media"
  },
  "followers": "https://p.farhan.codes/users/farhan/followers",
  "following": "https://p.farhan.codes/users/farhan/following",
  "id": "https://p.farhan.codes/users/farhan",
  "inbox": "https://p.farhan.codes/users/farhan/inbox",
  "manuallyApprovesFollowers": false,
  "name": "farhan",
  "outbox": "https://p.farhan.codes/users/farhan/outbox",
  "preferredUsername": "farhan",
  "publicKey": {
    "id": "https://p.farhan.codes/users/farhan#main-key",
    "owner": "https://p.farhan.codes/users/farhan",
    "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAn5JI+uBbt3w0tPekK+UD\naQLRG220XztYLEE1gC8eGYctYgrTX0wruNP+CFap1VsvyWxRoitNjFLDD3pwYxK9\n+k6P459ekL0fSRqQ0bzOQ5Vb22PBs9iOKonV9FSljCcDg0kc3cvxCeU246BMurGI\nIs0vWk3UwygkeMo+rYXDluTtuSvZs+2ume2JYgrtcQoDH5YzU+76dRLYfd1+xEFo\nP+K0hFb7+LhwGwDuLtTUYQ39kqm2jnC9/3W5yyweBqh05iQ0joDC0nuoZpjvT7on\n2Obwluci30Q2xS1i+5244qr9Ouq1EK+9kdf15RMMOH1Azumho1YNFoVZlcxy2bar\n6wIDAQAB\n-----END PUBLIC KEY-----\n"
  },
  "summary": "",
  "tag": [],
  "type": "Person",
  "url": "https://p.farhan.codes/users/farhan"
}

Still does not follow. In the case of a Mastodon server, it reports

Verification failed for farhan@p.farhan.codes https://p.farhan.codes/users/farhan

Are you sure you’re signing your requests correctly? Your actor object appears to be valid now, including the public key, at least Smithereen happily accepts it (see on my instance).

Edit: see my definitely working Java code for HTTP signatures. You may skip Digest, the part where you hash the entire request body, but be aware that some Mastodon instances won’t accept requests without it.

1 Like

Your python3 code is:

signed_message = '(request-target): {%s} {%s}\nhost: {%s}\ndate: {%s}' % (method, request_path, to_hostname, now)

Which is confusing the .format string syntax and the string interpolation operator.

Your signed_message on the playground looks like:

(request-target): {post} {../Playground/}
host: {ee880c3b32b8.ngrok.io}
date: {Tue, 10 Nov 2020 18:13:39 GMT}

Which is incorrectly adding the {}s.

Simply remove them:

signed_message = '(request-target): %s %s\nhost: %s\ndate: %s' % (method, request_path, to_hostname, now)