Changeset 691311f in Klonkt for src/services/ActivityPubService.js
- Timestamp:
- 08/06/2026 10:40:40 AM (5 weeks ago)
- Branches:
- main
- Children:
- 5d0d41d
- Parents:
- 57aee3b
- git-author:
- Robin <roboburr@…> (08/06/2026 10:40:39 AM)
- git-committer:
- Claude (agent) <aiclaude@…> (08/06/2026 10:40:40 AM)
- File:
-
- 1 edited
-
src/services/ActivityPubService.js (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/services/ActivityPubService.js
r57aee3b r691311f 1284 1284 } 1285 1285 1286 export async function fetchActor(url) { 1286 export async function fetchActor(url, opts = {}) { 1287 // Authorized fetch (Mastodons secure mode): zo'n instance serveert zijn 1288 // actor-document -- en dus zijn publieke sleutel -- alleen aan een ONDERTEKEND 1289 // verzoek en antwoordt anders met 401. Zonder sleutel kunnen we een correct 1290 // ondertekende Follow van die instance niet verifiëren en wijzen we hem af, 1291 // waarna Mastodon het dagenlang blijft proberen. Gemeten op boiert.eu: vier 1292 // accounts eindeloos geweigerd, en precies die vier geven 401 op een 1293 // onbetekende GET (shaer-afq). 1294 // 1295 // Geen kip-ei: om ONZE handtekening te controleren haalt de andere kant ons 1296 // actor-document op, en dat serveert Klonkt publiek. 1297 if (opts.asSlug) { 1298 const signed = await signedGetJson(opts.asSlug, url).catch(() => null); 1299 if (signed && signed.id) return signed; 1300 // Geen terugkeer bij mislukking: een instance zonder secure mode moet 1301 // blijven werken, en niet elke 401 komt van authorized fetch. 1302 } 1287 1303 try { 1288 1304 const r = await safeFetch(url, { headers: { Accept: 'application/activity+json' } }); … … 1368 1384 } 1369 1385 1386 /** Een lokale site om GETs mee te ondertekenen wanneer er geen specifieke is 1387 * (de gedeelde inbox). Gecached: dit draait per binnenkomend verzoek. */ 1388 let _signSlug; 1389 function anySigningSlug() { 1390 if (_signSlug !== undefined) return _signSlug; 1391 try { const r = db.prepare('SELECT slug FROM sites ORDER BY rowid LIMIT 1').get(); _signSlug = (r && r.slug) || null; } 1392 catch { _signSlug = null; } 1393 return _signSlug; 1394 } 1395 1370 1396 // Best-effort verification of an incoming signed request. Returns the sender's 1371 1397 // actor doc if the signature checks out, else null. (Not gating yet — MVP.) … … 1373 1399 // federating servers with drifting clocks; an operator can widen it via env. 1374 1400 const SIG_MAX_SKEW_MS = (Number(process.env.AP_SIG_MAX_SKEW_MIN) || 60) * 60 * 1000; 1375 export async function verifyRequest(req ) {1401 export async function verifyRequest(req, asSlug = null) { 1376 1402 const sigH = req.headers['signature']; 1377 1403 if (!sigH) return null; 1378 1404 const p = Object.fromEntries([...sigH.matchAll(/([a-zA-Z]+)="([^"]*)"/g)].map((m) => [m[1], m[2]])); 1379 1405 if (!p.keyId || !p.signature) return null; 1380 const actor = await fetchActor(p.keyId.split('#')[0]); 1406 // Onderteken de sleutel-ophaal, anders faalt elke instance met authorized 1407 // fetch (shaer-afq). Zonder aangewezen site -- de gedeelde inbox -- tekenen we 1408 // als een willekeurige lokale actor: elke Klonkt-actor is een geldige 1409 // ondertekenaar, het gaat de andere kant er alleen om DAT er ondertekend is. 1410 const actor = await fetchActor(p.keyId.split('#')[0], { asSlug: asSlug || anySigningSlug() }); 1381 1411 const pem = actor && actor.publicKey && actor.publicKey.publicKeyPem; 1382 1412 if (!pem) return null; … … 1678 1708 // keeps everything below identical, including the actor-versus-signer check, 1679 1709 // which is exactly the check that must not be skipped for being local. 1680 const verified = preVerified || await verifyRequest(req ).catch(() => null);1710 const verified = preVerified || await verifyRequest(req, slugParam).catch(() => null); 1681 1711 1682 1712 // ENFORCE HTTP signatures: a data-affecting activity must be signed by the very
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)