ckolderup / postmarks

a single-user bookmarking website designed to live on the Fediverse
https://postmarks.glitch.me
MIT License
452 stars 38 forks source link

Unable to follow a user on Betula #185

Open andypiper opened 5 months ago

andypiper commented 5 months ago

Attempting to follow a Betula user (Betula is currently adding AP support).

Following @bouncepaw@links.bouncepaw.com results in

couldn't look up canonical actor info
Invalid URL

This appears to be because WebFinger is only responding to bouncepaw@links.bouncepaw.com (without the leading @ so this is likely something to address in Postmarks, either in the UI validation for following users, or in the lookup code.

andypiper commented 5 months ago

Hmm, Postmarks follow request is not working with either format of username. To be investigated further asap.

andypiper commented 5 months ago

OK, tracked this down - Betula does not work with [domain]/.well-known/webfinger/?resource= only with [domain]/.well-known/webfinger?resource= so this looks like an edge case to be dug into.

I actually believe that the current code with / is incorrect here. https://datatracker.ietf.org/doc/html/rfc7033#section-4.1 and https://docs.joinmastodon.org/spec/webfinger/ seem to indicate that this should not have a trailing / at least, so we probably have a bug in Postmarks' WebFinger handling.

andypiper commented 5 months ago

Right. If I change the Postmarks code to remove the / character that upsets Betula, then Postmarks is seemingly able to make a call to the right spot, and I see the response come back - but then I see an error in parsing the JSON (if I manually log out the data that comes back)

Modified lookupActorInfo function.

// actorUsername format is @username@domain
export async function lookupActorInfo(actorUsername) {
  const parsedDomain = actorUsername.split('@').slice(-1);
  const parsedUsername = actorUsername.split('@').slice(-2, -1);
  try {
    const response = await fetch(`https://${parsedDomain}/.well-known/webfinger?resource=acct:${parsedUsername}@${parsedDomain}`);
    console.log(response);
    const data = await response.json();
    console.log('---');
    console.log(data);

    const selfLink = data.links.find((o) => o.rel === 'self');
    if (!selfLink || !selfLink.href) {
      throw new Error();
    }

    return selfLink.href;
  } catch (e) {
    console.log("couldn't look up canonical actor info");
    return null;
  }
}

Response:

[[2024-1-23 20:16:51] POST:/admin/following/follow 200 0.004ms - Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Response {
  size: 0,
  [Symbol(Body internals)]: {
    body: PassThrough {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 5,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: null
    },
    stream: PassThrough {
      _readableState: [ReadableState],
      _events: [Object: null prototype],
      _eventsCount: 5,
      _maxListeners: undefined,
      _writableState: [WritableState],
      allowHalfOpen: true,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: null
    },
    boundary: null,
    disturbed: false,
    error: null
  },
  [Symbol(Response internals)]: {
    type: 'default',
    url: 'https://links.bouncepaw.com/.well-known/webfinger?resource=acct:bouncepaw@links.bouncepaw.com',
    status: 200,
    statusText: 'OK',
    headers: {
      connection: 'close',
      'content-length': '197',
      'content-type': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
      date: 'Tue, 23 Jan 2024 20:16:52 GMT',
      server: 'nginx/1.14.0 (Ubuntu)'
    },
    counter: 0,
    highWaterMark: 16384
  }
}
---
{
  subject: 'acct:bouncepaw@links.bouncepaw.com',
  links: [
    {
      rel: 'self',
      type: 'application/activity+json',
      href: 'https://links.bouncepaw.com/@bouncepaw'
    }
  ]
}
Unexpected token < in JSON at position 0

This is super weird as the JSON looks fine to me. The error seems to indicate to me that the JSON parser is getting a bunch of HTML, not well-formed JSON. I am baffled right now. I'll continue to do some experimentation on this when I can.