Changeset 8501ee8 in Klonkt for FEDERATION.md


Ignore:
Timestamp:
08/19/2026 04:10:57 AM (3 weeks ago)
Author:
Bart <bart@…>
Branches:
main
Children:
70e9147
Parents:
192fe28
Message:

FEDERATION.md: OpenWebAuth erin, en de actor klopte niet meer

Twee dingen, en het tweede is een fout die er al stond.

OPENWEBAUTH (FEP-61cf) ontbrak volledig: niet bij de protocollen, niet in de
FEP-lijst, niet bij Authentication. Nu alle drie, met beide rollen apart
beschreven -- want dat is de vraag die een andere implementatie stelt: kan ik
hier binnenkomen, en kan ik van hieruit ergens anders heen. Met de vindbaarheid
(webfinger op de wortel voor het token-endpoint, #redirect op de actor), de
levensduur en eenmaligheid van tokens, en de drie dingen waar een implementatie
op stukloopt: Authorization in plaats van Signature, het mee-ondertekende
X-Open-Web-Auth, en dat ?zid= nooit een identiteit vaststelt.

EN DE ACTOR-SECTIE LOOG: "manuallyApprovesFollowers (currently always false)".

Dat is sinds Robins eigenaarspoort niet meer zo -- het is isWard

approve_followers. Een FEDERATION.md die een verkeerde bewering doet over wat er
op de draad staat is erger dan een die zwijgt, want een andere implementatie
richt zich ernaar. Meteen een korte sectie Follow approval erbij: wat er gebeurt
met een verzoek, wie beslist, en dat de guardianpoort vóórgaat.

Alles nagelopen tegen de code: de TTL, router.all op het token-endpoint, beide
webfinger-links, de uitdrukking voor manuallyApprovesFollowers, en dat accepteren
echt een Accept plus backfillNewFollower stuurt en weigeren een Reject.

Co-Authored-By: Claude Opus 5 <claude@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • FEDERATION.md

    r192fe28 r8501ee8  
    1414- [HTTP Signatures](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures) (draft-cavage), `rsa-sha256`
    1515- [NodeInfo](https://nodeinfo.diaspora.software/) 2.1
     16- [OpenWebAuth](https://codeberg.org/fediverse/fep/src/branch/main/fep/61cf/fep-61cf.md) single sign-on, both roles (see "Authentication")
    1617- [OAuth 2.0](https://www.rfc-editor.org/rfc/rfc6749) public clients with PKCE ([RFC 7636](https://www.rfc-editor.org/rfc/rfc7636), S256 only)
    1718- [OAuth 2.0 Authorization Server Metadata](https://www.rfc-editor.org/rfc/rfc8414) ([RFC 8414](https://www.rfc-editor.org/rfc/rfc8414))
     
    2829- [FEP-7628: Move actor](https://codeberg.org/fediverse/fep/src/branch/main/fep/7628/fep-7628.md) (DRAFT): account migration — `alsoKnownAs`, `movedTo` and the `Move` activity, sent and received. See "Account migration".
    2930- [FEP-1580: Move Actor Objects with a `migration` Collection](https://codeberg.org/fediverse/fep/src/branch/main/fep/1580/fep-1580.md) (DRAFT): the objects a `Move` leaves behind, exposed as a `migration` collection alongside `moves`.
     31- [FEP-61cf: The OpenWebAuth Protocol](https://codeberg.org/fediverse/fep/src/branch/main/fep/61cf/fep-61cf.md) (DRAFT): federated single sign-on, implemented in **both** roles. As a *target*, Klonkt lets a visitor from another server prove who they are and read follower-only posts without an account here. As a *home instance*, a site owner can sign in to another OpenWebAuth site using their own actor. See "Authentication".
    3032- [FEP-888d: Using `https://w3id.org/fep` as a base for FEP-specific namespaces](https://codeberg.org/fediverse/fep/src/branch/main/fep/888d/fep-888d.md) (DRAFT): the FEP-1580 terms are declared under `https://w3id.org/fep/1580/`, as that FEP registers them.
    3133
     
    5456under the legacy `publicKey` / `publicKeyPem` field
    5557([w3id security/v1](https://w3id.org/security/v1)). The actor advertises
    56 `discoverable`, `manuallyApprovesFollowers` (currently always `false`),
     58`discoverable`, `manuallyApprovesFollowers` (true for a ward, and for any site
     59with owner approval switched on — see "Follow approval"),
    5760`featured`, and profile metadata as `schema:PropertyValue` links (including
    5861`rel="me"` verification links). Actor and object requests are
     
    168171  (FEP-8b32) are not used.
    169172- C2S: OAuth 2.0 bearer tokens, public clients with PKCE (S256), scope `c2s`.
     173- Visitors: OpenWebAuth (FEP-61cf), described below.
     174
     175### OpenWebAuth (FEP-61cf)
     176
     177Klonkt implements both roles.
     178
     179**As a target instance.** A visitor enters their fediverse address; we WebFinger
     180it for a `http://purl.org/openwebauth/v1#redirect` link (falling back to `/magic`
     181on the same host, as Hubzilla and (streams) do) and send them there. Their server
     182then makes a signed request to our token endpoint at `/owa/token`, which accepts
     183both `GET` and `POST`. We verify the HTTP Signature with the same code path that
     184verifies inbox deliveries — the key is pinned to the origin the actor document
     185was fetched from, the signed `Date` must be recent, and a body requires a signed
     186digest — then return a single-use token encrypted to the actor's public key
     187(PKCS #1 v1.5, URL-safe Base64, unpadded). The visitor returns with `?owt=`, we
     188redeem the token once and know who they are.
     189
     190Discovery for the other side: a WebFinger query for this server's root URL
     191returns a `http://purl.org/openwebauth/v1` link pointing at `/owa/token`. An
     192actor's WebFinger response carries the `#redirect` link pointing at `/magic`.
     193
     194**As a home instance.** `/magic` takes an OpenWebAuth request for a logged-in
     195owner, discovers the target's token endpoint, requests a token over a signed
     196request, decrypts it with the site's private key and returns the visitor with
     197`?owt=`. On Klonkt the fediverse identity is the *site* actor, so an owner with
     198several sites picks which one to present. There is a consent screen: FEP-61cf
     199warns under "Information leakage" that OpenWebAuth hands a strong identity claim
     200to any site that asks, so the detour through the home instance is where the user
     201can decline.
     202
     203Notes for implementers:
     204
     205- The signature travels in `Authorization: Signature …`, as FEP-61cf requires,
     206  not in the `Signature` header the rest of the fediverse uses. Our token
     207  endpoint accepts either.
     208- Signed requests we send also carry a signed `X-Open-Web-Auth` header with
     209  random content, per the FEP.
     210- `?zid=` may start the flow but never establishes identity; only a redeemed
     211  `?owt=` does. `?owt=` is stripped from the URL after redemption.
     212- Tokens are single-use and expire after three minutes; expired ones are swept
     213  on every issue and redemption.
     214- A discovered endpoint must share the origin it was discovered for. If
     215  discovery fails, `/magic` returns an error rather than redirecting, so it
     216  cannot be used as an open redirector.
     217
     218What this unlocks: `fan_only` posts. That gate used to ask for a local account,
     219which is the wrong question — it excluded exactly the followers it was meant to
     220admit. It now asks whether the proven actor follows this site.
     221
     222### Follow approval
     223
     224A site can require the owner to approve followers. With it on, the actor
     225advertises `manuallyApprovesFollowers: true`, an inbound `Follow` is held
     226pending instead of auto-accepted, and the owner accepts (sending `Accept` plus a
     227backfill) or rejects (sending `Reject`). Ward actors always gate this way
     228through their guardians, which takes precedence. A pending request is not a
     229follower, and so does not open follower-only posts.
    170230
    171231## Moderation and safety
     
    203263- Source code: `src/services/ActivityPubService.js` (core AP logic),
    204264  `src/routes/activitypub.js` (S2S, WebFinger, NodeInfo),
    205   `src/routes/oauth.js` (C2S / OAuth).
     265  `src/routes/oauth.js` (C2S / OAuth),
     266  `src/services/OpenWebAuthService.js` and `src/routes/openwebauth.js`
     267  (OpenWebAuth, both roles).
    206268- Changelog: `CHANGELOG.md` (and `CHANGELOG.nl.md`, `CHANGELOG.de.md`).
Note: See TracChangeset for help on using the changeset viewer.