silverpill
silverpill boosted

ActivityPub: Client to Server endpoint discovery

I’ve re-started building with ActivityPub’s #c2s API based app. So this post is to document some of the challenges and hiccups.

  1. The very first thing a user will want to do is login, right? So, we ask the user for their instance URL or their handle (webfinger: user@domain.tld).
  2. Our app then needs to find an info about how to connect to the site.

    Luckily, the OAuth 2.0 standard exists! In our case we would be looking to RFC 8414: OAuth 2.0 Authorization Server Metadata. The main point is that once we have a server URL, we can look up the configuration routes via a predictable URL /.well-known/oauth-authorization-server

    If this route doesn’t exist then we have some alternatives. We could look for the instance actor.

    Depending on implementation, we might find this via nodeinfo (FEP-2677), or we might find it via webfinger (FEP-d556).

    1. The nodeinfo route is the more convoluted one, because fetching example.social/.well-known/nodeinfo we potentially receive a payload with links to version 2.0, and or 2.1. example.social/nodeinfo/2.1.

      This would lead us to parsing nodeinfo’s metadata field, looking for staffAccounts which would be an array, let’s just take the first one.

    2. The webfinger route would be: example.social/.well-known/webfinger?resource=https://example.social

      From there we parse the webfinger links field which is an array, looking for an object whose has rel=”self” and whose type="application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"".

      Whew, this object’s href value leads us to the instance actor.

    3. Finally, we arrive at an actor profile, where we will look for the endpoints field, and hope to find*:
      • oauthRegistrationEndpoint
      • oauthAuthorizationEndpoint
      • oauthTokenEndpoint
      • *However here too the road can be fraught with dangers… a number of servers are not allowing CORS requests on actor profiles.

        If implementations aren’t serving an oauth discovery endpoint RFC8414, and are limiting requests to actor pages, then there is really not much we can do!

  • FEP-d556: Server-Level Actor Discovery Using WebFinger
  • FEP-2677: Identifying the Application Actor
  • FEP-d8c2: OAuth 2.0 Profile for the ActivityPub API

#c2s

ActivityPub: Client to Server endpoint discovery

I’ve re-started building with ActivityPub’s #c2s API based app. So this post is to document some of the challenges and hiccups.

  1. The very first thing a user will want to do is login, right? So, we ask the user for their instance URL or their handle (webfinger: user@domain.tld).
  2. Our app then needs to find an info about how to connect to the site.

    Luckily, the OAuth 2.0 standard exists! In our case we would be looking to RFC 8414: OAuth 2.0 Authorization Server Metadata. The main point is that once we have a server URL, we can look up the configuration routes via a predictable URL /.well-known/oauth-authorization-server

    If this route doesn’t exist then we have some alternatives. We could look for the instance actor.

    Depending on implementation, we might find this via nodeinfo (FEP-2677), or we might find it via webfinger (FEP-d556).

    1. The nodeinfo route is the more convoluted one, because fetching example.social/.well-known/nodeinfo we potentially receive a payload with links to version 2.0, and or 2.1. example.social/nodeinfo/2.1.

      This would lead us to parsing nodeinfo’s metadata field, looking for staffAccounts which would be an array, let’s just take the first one.

    2. The webfinger route would be: example.social/.well-known/webfinger?resource=https://example.social

      From there we parse the webfinger links field which is an array, looking for an object whose has rel=”self” and whose type="application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"".

      Whew, this object’s href value leads us to the instance actor.

    3. Finally, we arrive at an actor profile, where we will look for the endpoints field, and hope to find*:
      • oauthRegistrationEndpoint
      • oauthAuthorizationEndpoint
      • oauthTokenEndpoint
      • *However here too the road can be fraught with dangers… a number of servers are not allowing CORS requests on actor profiles.

        If implementations aren’t serving an oauth discovery endpoint RFC8414, and are limiting requests to actor pages, then there is really not much we can do!

  • FEP-d556: Server-Level Actor Discovery Using WebFinger
  • FEP-2677: Identifying the Application Actor
  • FEP-d8c2: OAuth 2.0 Profile for the ActivityPub API

#c2s

Jeff Sikes 🍎
Sean Tilley
Jeff Sikes 🍎 and 1 other boosted
@deadsuperhero

Good opportunity to pass along this collection I keep of #ActivityPub#C2S related resources, to become part of the fediverse experience curated list..

https://delightful.coding.social/delightful-fediverse-experience

The list is in this codeberg issue:

https://codeberg.org/fediverse/delightful-fediverse-experience/issues/130

Sean Tilley
Sean Tilley liked this activity
@deadsuperhero

Good opportunity to pass along this collection I keep of #ActivityPub#C2S related resources, to become part of the fediverse experience curated list..

https://delightful.coding.social/delightful-fediverse-experience

The list is in this codeberg issue:

https://codeberg.org/fediverse/delightful-fediverse-experience/issues/130

@deadsuperhero

Good opportunity to pass along this collection I keep of #ActivityPub#C2S related resources, to become part of the fediverse experience curated list..

https://delightful.coding.social/delightful-fediverse-experience

The list is in this codeberg issue:

https://codeberg.org/fediverse/delightful-fediverse-experience/issues/130

just small circles 🕊
Tim Chambers
just small circles 🕊 and 1 other boosted

"A core objective of Flowz is flexibility and graceful degradation. Even when connected to a server that supports only the minimal core C2S functionality, the client still delivers a reasonable user experience. Users can perform essential actions such as reading timelines and posting updates. However, where Flowz really shines is when it connects to servers that offer extended C2S capabilities."

@stevebate, 2025

https://www.stevebate.net/activitypub-client-api-a-way-forward/

(1/3)

#ActivityPub#C2S#Flowz

"A core objective of Flowz is flexibility and graceful degradation. Even when connected to a server that supports only the minimal core C2S functionality, the client still delivers a reasonable user experience. Users can perform essential actions such as reading timelines and posting updates. However, where Flowz really shines is when it connects to servers that offer extended C2S capabilities."

@stevebate, 2025

https://www.stevebate.net/activitypub-client-api-a-way-forward/

(1/3)

#ActivityPub#C2S#Flowz

@kfdm yes, the information needed to be scraped together. Don't hesitate to add a comment if you find more useful resources around C2S. There is an uptick in interest on the subject currently.

I may create a seperate #C2S section in the delightful #ActivityPub development list, which is to be revamped in similar way as recently the #fediverse experience list.

https://delightful.coding.social/delightful_activitypub_development

@kfdm yes, the information needed to be scraped together. Don't hesitate to add a comment if you find more useful resources around C2S. There is an uptick in interest on the subject currently.

I may create a seperate #C2S section in the delightful #ActivityPub development list, which is to be revamped in similar way as recently the #fediverse experience list.

https://delightful.coding.social/delightful_activitypub_development

Lists like https://codeberg.org/fediverse/delightful-fediverse-experience show several server projects for #activitypub , a few that list #c2s but haven't had much luck finding a list of apps that support c2s. I guess it's a chicken/egg problem in many ways. I'd sometimes like to experiment with my own c2s+s2s server implementation, but it's a bit of a larger hurdle if there aren't any c2s desktop/mobile apps to help test with. 🤔

Idle thought re: account delegation

I've been toying with the idea of using OAuth2/OpenID and the C2S API to have a service act on behalf of another instance (e.g. act on Lemmy, post as Mastodon account)

But now I'm wondering whether that kind of complexity is needed... one could theoretically register a public key to the instance it is acting on behalf of, and simply sign activities using the ID of the other server... Second server would need only update the actor with the new public key for verification purposes...

I've been toying with the idea of using OAuth2/OpenID and the C2S API to have a service act on behalf of another instance (e.g. act on Lemmy, post as Mastodon account)

But now I'm wondering whether that kind of complexity is needed... one could theoretically register a public key to the instance it is acting on behalf of, and simply sign activities using the ID of the other server... Second server would need only update the actor with the new public key for verification purposes...

Lists like https://codeberg.org/fediverse/delightful-fediverse-experience show several server projects for #activitypub , a few that list #c2s but haven't had much luck finding a list of apps that support c2s. I guess it's a chicken/egg problem in many ways. I'd sometimes like to experiment with my own c2s+s2s server implementation, but it's a bit of a larger hurdle if there aren't any c2s desktop/mobile apps to help test with. 🤔

Idle thought re: account delegation

I've been toying with the idea of using OAuth2/OpenID and the C2S API to have a service act on behalf of another instance (e.g. act on Lemmy, post as Mastodon account)

But now I'm wondering whether that kind of complexity is needed... one could theoretically register a public key to the instance it is acting on behalf of, and simply sign activities using the ID of the other server... Second server would need only update the actor with the new public key for verification purposes...

I've been toying with the idea of using OAuth2/OpenID and the C2S API to have a service act on behalf of another instance (e.g. act on Lemmy, post as Mastodon account)

But now I'm wondering whether that kind of complexity is needed... one could theoretically register a public key to the instance it is acting on behalf of, and simply sign activities using the ID of the other server... Second server would need only update the actor with the new public key for verification purposes...

I've been thinking about client-server interactions in the #fediverse. #ActivityPub #C2S isn't widely used, and most clients rely on Mastodon-compatible APIs instead.

What if we created a new standardized API based on GraphQL + Relay for client-server communication, while keeping ActivityPub for server-to-server federation?

The Mastodon-compatible API lacks formal schema definitions for code generation and type checking, which hurts developer productivity. And ActivityPub C2S is honestly too cumbersome to use directly from client apps.

#GraphQL would give us type safety, efficient data fetching (only get what you need), and the ability to evolve the API without breaking clients. #Relay's features for pagination, caching, and optimistic updates seem perfect for social apps.

Would this be valuable to our community? What challenges do you see? How might we handle backward compatibility? And should this be formalized as an FEP?

Curious what others think about this approach.

#fedidev

@josemurilo yes, remarkable.

I keep track of a list of #ActivityPub#C2S implementations at the newly revamped https://delightful.coding.social/delightful-fediverse-experience

See: https://codeberg.org/fediverse/delightful-fediverse-experience/issues/130

PS. @box464 also tooted about this today and I dropped off the codeberg issue too. I hope to find more C2S implementers or would-be ones.

People keep pointing out the UX fail of expecting people to have multiple accounts to use all the different fedi services. But that wouldn't be true if every #AP app and server used a general purpose #C2S API, defined in the AP spec (whether the existing one or not).

Then we could, for example, use a Mastodon account to login to a PeerTube service to browse and post videos. Or use a PT account to login to a Mastodon service to browse and post Notes.

@tchambers@rakoo @benpate @jupiter_rowland

@strypey@rakoo @benpate @jupiter_rowland True that. Has anyone even got an alpha version of a #c2s app running?

People keep pointing out the UX fail of expecting people to have multiple accounts to use all the different fedi services. But that wouldn't be true if every #AP app and server used a general purpose #C2S API, defined in the AP spec (whether the existing one or not).

Then we could, for example, use a Mastodon account to login to a PeerTube service to browse and post videos. Or use a PT account to login to a Mastodon service to browse and post Notes.

@tchambers@rakoo @benpate @jupiter_rowland

People keep pointing out the UX fail of expecting people to have multiple accounts to use all the different fedi services. But that wouldn't be true if every #AP app and server used a general purpose #C2S API, defined in the AP spec (whether the existing one or not).

Then we could, for example, use a Mastodon account to login to a PeerTube service to browse and post videos. Or use a PT account to login to a Mastodon service to browse and post Notes.

@tchambers@rakoo @benpate @jupiter_rowland