Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ActivityPub ids with # symbol are not resolvable #13879

Open
koehn opened this issue May 27, 2020 · 11 comments
Open

ActivityPub ids with # symbol are not resolvable #13879

koehn opened this issue May 27, 2020 · 11 comments
Labels
partially a bug Architecture or design-imposed shortcomings

Comments

@koehn
Copy link

koehn commented May 27, 2020

Expected behaviour

Per the ActivityPub specification, IDs must either be null or:

Publicly dereferencable URIs, such as HTTPS URIs, with their authority belonging to that of their originating server. (Publicly facing content SHOULD use HTTPS URIs).

Actual behaviour

Mastodon ids include information in the fragment (#) section, which renders the portion of the ID beyond the fragment symbol as unresolvable by HTTP-conforming libraries such as libcurl.

Steps to reproduce the problem

curl -vH 'Accept: application/activity+json' 'https://mastodon.technology/@norztech#likes/836349#Like'

curl (correctly) sends:

> GET /@norztech HTTP/2
> Host: mastodon.technology
> User-Agent: curl/7.64.1
> Accept: application/activity+json
@koehn
Copy link
Author

koehn commented May 27, 2020

Related to friendica/friendica#8700

@nightpool
Copy link
Member

These URLs aren't intended to be resolvable currently, yes. We created unique identifiers in this case to encourage compatibility with some other integrations that wanted Likes to be uniquely identifiable.

However, i don't think saying that fragment URLs in general aren't resolvable is correct—to resolve an identifier like https://cybre.space/users/nightpool#main-key, you can fetch https://cybre.space/users/nightpool and then look for the object in the graph with the id https://cybre.space/users/nightpool#main-key.

@koehn
Copy link
Author

koehn commented Jun 8, 2020

You make a valid point, however multiple # symbols in a URL violates the URL specification; also the likes in question don't exist in the JSON returned.

@Gargron
Copy link
Member

Gargron commented Jun 8, 2020

I think we only put one # into the IDs, not sure where the #Like in your example comes from as I don't remember putting it there...

@nightpool
Copy link
Member

nightpool commented Jun 8, 2020

@koehn yeah, you're correct, the Likes in question are intentionally non-resolvable since we haven't built that, but we added a unique id for other apps that did want a unique identifier and didn't care about resolvability. I would recommend we either add a unique, resolvable route for a user's likes, or remove the id altogether (as recommended by the spec for ephemeral objects).

One security concern that makes things a little complicated here is the possibility of enumeration. We definitely don't want to make user's likes enumerable. @koehn if the likes endpoint was unique, but returned a 403 for anyone except the user whose content was liked, would that work for you? (not saying we're going to build that, just wondering about your use-case)

@Gargron
Copy link
Member

Gargron commented Jun 8, 2020

Null-IDs are not desired because then managing the undos becomes impossible if they arrive out of order.

@nightpool
Copy link
Member

nightpool commented Jun 8, 2020

@Gargron it's stilo possible, but it does get slightly more complicated. I would do something like:

  1. when you see an undo, DECR a redis key based on (type, actor, object).
    a. if the key = 0, delete the appropriate Like.
  2. when you see a Like, INCR the same key.
    a. if the key = 1, create the object.

So if, for example, you get 3 deletes followed by 2 likes, you'll end up at -1, and never create a Like object.

(this does remove the ability to distinguish between retransmission of old events and new events, but we could handle that by including another high-entropy property, like created_at with millisecond precision, and go back to the old single-boolean key algorithm)

@koehn
Copy link
Author

koehn commented Jun 8, 2020

My use case is this:

  1. There are users A, B, and C. Users B & C both follow user A. All are on different servers
    A. User A is on Friendica;
    B. User B is on Mastodon;
    C. User C is on my server.
  2. User A creates a Note and sends it to Users B & C. So far so good.
  3. User B likes the Note and sends a Like to user A. The like has a non-resolvable ID.
  4. User A's server receives the Like and attempts to federate it by sending it to User C, who is on my server.
  5. Seeing that the Like is sent by User A (based on http-signature), but the actor is User C, my server decides not to trust that User A's message is valid, so my server tries to get it's own copy from User B's server. That doesn't work because the ID isn't actually resolvable.
  6. Here we are.

Honestly the way that this gets federated is bizarre to me (it seems that User B's server should be sending the Like to Users A & C, but 🤷🏼‍♂️). But I haven't yet learned the nuances of how different servers deliver messages in ActivityPub.

@koehn
Copy link
Author

koehn commented Jun 8, 2020

FWIW this is a lot simpler in an NoSQL database.

@nightpool
Copy link
Member

nightpool commented Jun 8, 2020

Hmm.... what is the audience of the Likes we're currently sending? I don't believe they're meant to be disclosed/retransmitted publicly like that.

I don't know what people's current expectations of privacy are around Likes and I wouldn't want to introduce something that would violate those expectations by showing them to a third party without first providing users with more explicit privacy toggles

@vpzomtrrfrt
Copy link
Contributor

See also #13571

snarfed added a commit to snarfed/bridgy-fed that referenced this issue Feb 16, 2023
this is still underspecified and a bit inconsistent across fediverse implementations:

https://socialhub.activitypub.rocks/t/problems-posting-to-mastodon-inbox/801/11

> The reason might also be that your IDs aren’t permanent, as in, they contain a #fragment. Posts and their corresponding Create activities are supposed to be resolvable — which means one should be able to send a GET request to the ID URL and get the object back. This can’t be done with an URL that contains a fragment as the fragment is not a part of the HTTP exchange, it’s processed on the client.

https://socialhub.activitypub.rocks/t/problems-posting-to-mastodon-inbox/801/23

> I ran into this object id #fragment problem as well. It seems because of some URL normalization, Mastodon will remove the fragment, and drop any additional posts with different fragments (because they become the same url).

https://socialhub.activitypub.rocks/t/s2s-create-activity/1647/5
mastodon/mastodon#13879 (open!)
w3c/activitypub#224

nothing in the http sig spec, example key ids aren't even URLs there:
https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-message-signatures-16
@vmstan vmstan added the partially a bug Architecture or design-imposed shortcomings label Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
partially a bug Architecture or design-imposed shortcomings
Projects
None yet
Development

No branches or pull requests

5 participants