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

WebFinger doesn't allow querying by actor uri #5068

Closed
zotanmew opened this issue May 1, 2024 · 15 comments
Closed

WebFinger doesn't allow querying by actor uri #5068

zotanmew opened this issue May 1, 2024 · 15 comments

Comments

@zotanmew
Copy link

zotanmew commented May 1, 2024

Heya, the Pixelfed WebFinger implementation currently doesn't appear to support querying by ?resource=https://instance.tld/users/username. This is required for spec-compliance, and therefore federation with several other ActivityPub implementations that fail to resolve Pixelfed users without this. It'd be appreciated if you could add this!

@trwnh
Copy link
Member

trwnh commented May 1, 2024

this is not required. which implementations are having issues, and what are the issues?

@zotanmew
Copy link
Author

zotanmew commented May 1, 2024

Iceshrimp.NET currently can't resolve pixelfed users for this reason. I'll check the spec again to be sure, I may be mistaken.

@zotanmew
Copy link
Author

zotanmew commented May 1, 2024

If i'm reading the spec correctly, it specifies that URIs under aliases identify the same entity as subject. (section 4.4.2). I'd conclude from this that they should be usable as a query target URI /resource as per section 4.1. Mastodon/pleroma/misskey/gotosocial all implement it in this way as well, though they presumably don't rely on it.

@zotanmew
Copy link
Author

zotanmew commented May 1, 2024

The reason we're querying the uri via webfinger is that it's the only way to obtain information on the split-domain configuration of the remote instance (whereby the accounts are registered under @instance.tld but the instance is reachable under web.instance.tld or similar)

@trwnh
Copy link
Member

trwnh commented May 2, 2024

should, not must

the way you set up different web-domain and local-domain is to redirect webfinger requests from local-domain to web-domain

but you already have the id of the user so you do something like this:

  • do a webfinger for acct:preferredUsername@webdomain against webdomain
  • you should get redirected to the same query against localdomain
  • if the self-link points back to the id you started with, take the subject

https://swicg.github.io/activitypub-webfinger/#reverse-discovery

https://docs.joinmastodon.org/admin/config/#web_domain

https://docs-develop.pleroma.social/backend/configuration/how_to_serve_another_domain_for_webfinger/#configuring-webfinger-domain

https://docs.gotosocial.org/en/latest/advanced/host-account-domain/

@zotanmew
Copy link
Author

zotanmew commented May 2, 2024

My point is that with the way the code is currently structured, WebFinger always comes before the AP fetch. Refactoring this would take ages & I'm sure we won't be the last implementation having issues like this. Would it be that difficult to check whether the resource being queried points to a local user? I can even send a PR if required, though my PHP is very rusty.

@trwnh
Copy link
Member

trwnh commented May 2, 2024

webfinger shouldn't be necessary if you already have the actor id. how hard is it to just skip webfinger? something like the following pseudocode:

def get_actor_document(x):
  if x.startswith('https'):
    actor_document = get(x, headers={'accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'})

  else:
    username, domain = x.split('@', 2)
    jrd = get(f'https://{domain}/.well-known/webfinger?resource=acct:{username}@{domain}', headers={'accept': 'application/jrd+json'})
    actor_id = filter(jrd, rel='self').href
    actor_document = get(actor_id, headers={'accept': 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'})

then you can construct the webfinger acct: uri following reverse discovery, in order to verify it

@zotanmew
Copy link
Author

zotanmew commented May 2, 2024

The issue is that using this you cannot figure out the canonical domain for a split domain user, since the AP payload never tells you what it's supposed to be. You have to webfinger the URI to do this. You can't even ask the remote instance for ?resource=preferredUsername after fetching it, because on AP platforms like takahe there may be more than one user with the same preferredUsername, on different accountDomains.

@zotanmew
Copy link
Author

zotanmew commented May 2, 2024

It'd be a lot of work to refactor this logic on my side, and it would just be one extra check (starts with http/s) and db query on your end.

Also, specifications are one thing in ActivityPub, we all know that to federate with everyone you have to implement what everyone else does, which isn't necessarily what the spec says. In this case, all the major implementations support this, so whether the spec says it's required or not, supporting it is a good idea regardless to ensure compatibility.

@trwnh
Copy link
Member

trwnh commented May 2, 2024

you cannot figure out the canonical domain for a split domain user

you can. do reverse discovery.

to be clear, this is what it looks like when you do forward discovery and then verify with reverse discovery:

forward discovery

  • start with a@trwnh.com
  • do a webfinger for that acct: at that host, e.g. https://trwnh.com/.well-known/webfinger?resource=acct:a@trwnh.com
  • take the self link which can be something like https://ap.trwnh.com/actors/1

reverse discovery

  • start with https://ap.trwnh.com/actors/1
  • extract preferredUsername a and hostname ap.trwnh.com, do a webfinger at e.g. https://ap.trwnh.com/.well-known/webfinger?resource=acct:a@ap.trwnh.com
  • make sure the self link matches the actor you started with
  • take the JRD subject as canonical

this shouldn't be hard. it's what "all the major implementations" do to get your canonical webfinger address.

You have to webfinger the URI to do this

no, you webfinger the preferredUsername@web_domain. you shouldn't have to webfinger the https uri for an actor under any circumstances.

@zotanmew
Copy link
Author

zotanmew commented May 2, 2024

I'm aware how this works, I've talked to people who co-wrote the AP spec. I can assure you that this is anything but easy to implement on our side.

We'd have to refactor several hundreds of lines of code that was really annoying to get right to begin with, to support a quirk of a different piece of AP software, that diverges from what mastodon does. I'm not going to spend several days rewriting hundreds of lines of critical federation code just to federate with Pixelfed.

Again, I'm happy to write a PR for this, I don't understand why you're so reluctant to make/merge this tiny compatibility change that would allow for federation with more services.

@trwnh
Copy link
Member

trwnh commented May 3, 2024

the change isn't unwelcome, but i'm trying to point out that you are probably going to have issues in the future like this, and there's a high chance you're overcomplicating your code by doing something you shouldn't be doing. if it's "hundreds of lines" as you say, then that's almost certainly the case.

@rimu
Copy link

rimu commented May 17, 2024

This would be really simple on the pixelfed side:

        query = request.args.get('resource')  # e.g. query value: "acct:alice@tada.club"
        if 'acct:' in query:
            actor = query.split(':')[1].split('@')[0]  # alice
        elif 'https:' in query or 'http:' in query:
            actor = query.split('/')[-1]                        # alice
        else:
            return 'Webfinger regex failed to match'

it's maybe 3 extra lines.

@dansup dansup closed this as completed in 24194f7 May 23, 2024
@dansup
Copy link
Member

dansup commented May 23, 2024

@rimu @zotanmew I just shipped support for this, feel free to re-open if you run into any issues. This is live on pixelfed.social if you want to test it btw!

@zotanmew
Copy link
Author

zotanmew commented May 23, 2024

@dansup thank you so much! one tiny nitpick (though I'm happy to add support for this on our end Update: added support for it on our end.) is that one of the aliases (instance.tld/username) still causes webfinger to return 400. Would be nice if you could add that, though it's not critical. The patch as-is fixed most of our federation issues with pixelfed, and the ones that remain I can easily work around on our end. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants