fedimbed: finally impl request signing
untested
This commit is contained in:
parent
78026c7aeb
commit
9af670dbeb
4 changed files with 155 additions and 11 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,4 +1,5 @@
|
|||
node_modules/
|
||||
priv/
|
||||
|
||||
config.json
|
||||
config.prod.json
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
"homepage": "https://gitdab.com/Cynosphere/HiddenPhox#readme",
|
||||
"dependencies": {
|
||||
"@ctrl/tinycolor": "^3.6.0",
|
||||
"@peertube/http-signature": "^1.7.0",
|
||||
"@projectdysnomia/dysnomia": "^0.1.2",
|
||||
"dumpy": "github:Cynosphere/dumpy.js",
|
||||
"google-images": "^2.1.0",
|
||||
|
|
106
pnpm-lock.yaml
106
pnpm-lock.yaml
|
@ -4,6 +4,9 @@ dependencies:
|
|||
'@ctrl/tinycolor':
|
||||
specifier: ^3.6.0
|
||||
version: 3.6.0
|
||||
'@peertube/http-signature':
|
||||
specifier: ^1.7.0
|
||||
version: 1.7.0
|
||||
'@projectdysnomia/dysnomia':
|
||||
specifier: ^0.1.2
|
||||
version: 0.1.2
|
||||
|
@ -898,6 +901,15 @@ packages:
|
|||
dev: false
|
||||
optional: true
|
||||
|
||||
/@peertube/http-signature@1.7.0:
|
||||
resolution: {integrity: sha512-aGQIwo6/sWtyyqhVK4e1MtxYz4N1X8CNt6SOtCc+Wnczs5S5ONaLHDDR8LYaGn0MgOwvGgXyuZ5sJIfd7iyoUw==}
|
||||
engines: {node: '>=0.10'}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
jsprim: 1.4.2
|
||||
sshpk: 1.17.0
|
||||
dev: false
|
||||
|
||||
/@projectdysnomia/dysnomia@0.1.2:
|
||||
resolution: {integrity: sha512-F64G64JwFWn/QUFqkhsyBvXJ0Du3E6Y0yu8tSrcukAnSeW8qV+reKqeQnMmHcQWYopwuYM8Q6OF/VX6VKggtOA==}
|
||||
engines: {node: '>=10.4.0'}
|
||||
|
@ -1057,6 +1069,17 @@ packages:
|
|||
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
|
||||
dev: true
|
||||
|
||||
/asn1@0.2.6:
|
||||
resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==}
|
||||
dependencies:
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
|
||||
/assert-plus@1.0.0:
|
||||
resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
|
||||
engines: {node: '>=0.8'}
|
||||
dev: false
|
||||
|
||||
/balanced-match@1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
|
||||
|
@ -1064,6 +1087,12 @@ packages:
|
|||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
dev: false
|
||||
|
||||
/bcrypt-pbkdf@1.0.2:
|
||||
resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==}
|
||||
dependencies:
|
||||
tweetnacl: 0.14.5
|
||||
dev: false
|
||||
|
||||
/bl@4.1.0:
|
||||
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
|
||||
dependencies:
|
||||
|
@ -1218,6 +1247,10 @@ packages:
|
|||
resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==}
|
||||
dev: false
|
||||
|
||||
/core-util-is@1.0.2:
|
||||
resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
|
||||
dev: false
|
||||
|
||||
/create-error-class@3.0.2:
|
||||
resolution: {integrity: sha512-gYTKKexFO3kh200H1Nit76sRwRtOY32vQd3jpAQKpLtZqyNsSQNfI4N7o3eP2wUjV35pTWKRYqFUDBvUha/Pkw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -1253,6 +1286,13 @@ packages:
|
|||
resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==}
|
||||
dev: false
|
||||
|
||||
/dashdash@1.14.1:
|
||||
resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==}
|
||||
engines: {node: '>=0.10'}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
dev: false
|
||||
|
||||
/debug@4.3.4:
|
||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
|
@ -1337,6 +1377,13 @@ packages:
|
|||
resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==}
|
||||
dev: false
|
||||
|
||||
/ecc-jsbn@0.1.2:
|
||||
resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==}
|
||||
dependencies:
|
||||
jsbn: 0.1.1
|
||||
safer-buffer: 2.1.2
|
||||
dev: false
|
||||
|
||||
/emoji-regex@8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
dev: false
|
||||
|
@ -1480,6 +1527,11 @@ packages:
|
|||
engines: {node: '>=6'}
|
||||
dev: false
|
||||
|
||||
/extsprintf@1.3.0:
|
||||
resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==}
|
||||
engines: {'0': node >=0.6.0}
|
||||
dev: false
|
||||
|
||||
/fast-deep-equal@3.1.3:
|
||||
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
|
||||
dev: true
|
||||
|
@ -1583,6 +1635,12 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/getpass@0.1.7:
|
||||
resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
dev: false
|
||||
|
||||
/gifwrap@0.9.4:
|
||||
resolution: {integrity: sha512-MDMwbhASQuVeD4JKd1fKgNgCRL3fGqMM4WaqpNhWO0JiMOAjbQdumbs4BbBZEy9/M00EHEjKN3HieVhCUlwjeQ==}
|
||||
dependencies:
|
||||
|
@ -1890,14 +1948,32 @@ packages:
|
|||
argparse: 2.0.1
|
||||
dev: true
|
||||
|
||||
/jsbn@0.1.1:
|
||||
resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==}
|
||||
dev: false
|
||||
|
||||
/json-schema-traverse@0.4.1:
|
||||
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
|
||||
dev: true
|
||||
|
||||
/json-schema@0.4.0:
|
||||
resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==}
|
||||
dev: false
|
||||
|
||||
/json-stable-stringify-without-jsonify@1.0.1:
|
||||
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
|
||||
dev: true
|
||||
|
||||
/jsprim@1.4.2:
|
||||
resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==}
|
||||
engines: {node: '>=0.6.0'}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
extsprintf: 1.3.0
|
||||
json-schema: 0.4.0
|
||||
verror: 1.10.0
|
||||
dev: false
|
||||
|
||||
/levn@0.4.1:
|
||||
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
@ -2476,7 +2552,6 @@ packages:
|
|||
/safer-buffer@2.1.2:
|
||||
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/sax@1.2.4:
|
||||
resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==}
|
||||
|
@ -2593,6 +2668,22 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/sshpk@1.17.0:
|
||||
resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
asn1: 0.2.6
|
||||
assert-plus: 1.0.0
|
||||
bcrypt-pbkdf: 1.0.2
|
||||
dashdash: 1.14.1
|
||||
ecc-jsbn: 0.1.2
|
||||
getpass: 0.1.7
|
||||
jsbn: 0.1.1
|
||||
safer-buffer: 2.1.2
|
||||
tweetnacl: 0.14.5
|
||||
dev: false
|
||||
|
||||
/ssri@8.0.1:
|
||||
resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -2723,6 +2814,10 @@ packages:
|
|||
safe-buffer: 5.2.1
|
||||
dev: false
|
||||
|
||||
/tweetnacl@0.14.5:
|
||||
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
|
||||
dev: false
|
||||
|
||||
/tweetnacl@1.0.3:
|
||||
resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==}
|
||||
requiresBuild: true
|
||||
|
@ -2800,6 +2895,15 @@ packages:
|
|||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||
dev: false
|
||||
|
||||
/verror@1.10.0:
|
||||
resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==}
|
||||
engines: {'0': node >=0.6.0}
|
||||
dependencies:
|
||||
assert-plus: 1.0.0
|
||||
core-util-is: 1.0.2
|
||||
extsprintf: 1.3.0
|
||||
dev: false
|
||||
|
||||
/webidl-conversions@3.0.1:
|
||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
||||
dev: false
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
const {MessageFlags} = require("@projectdysnomia/dysnomia").Constants;
|
||||
const fs = require("node:fs");
|
||||
const path = require("node:path");
|
||||
const httpSignature = require("@peertube/http-signature");
|
||||
|
||||
const events = require("../lib/events.js");
|
||||
const logger = require("../lib/logger.js");
|
||||
|
@ -64,6 +67,38 @@ async function resolvePlatform(url) {
|
|||
return nodeinfo.software.name;
|
||||
}
|
||||
|
||||
const keyId = "https://hf.c7.pm/action#main-key";
|
||||
const privKey = fs.readFileSync(path.resolve("../../priv/private.pem"));
|
||||
async function signedFetch(url, options) {
|
||||
const urlObj = new URL(url);
|
||||
|
||||
const headers = {
|
||||
host: urlObj.host,
|
||||
date: new Date().toUTCString(),
|
||||
};
|
||||
|
||||
const headerNames = ["(request-target)", "host", "date"];
|
||||
|
||||
httpSignature.sign(
|
||||
{
|
||||
getHeader: (name) => headers[name.toLowerCase()],
|
||||
setHeader: (name, value) => (headers[name] = value),
|
||||
method: options.method ?? "GET",
|
||||
path: urlObj.pathname,
|
||||
},
|
||||
{
|
||||
keyId,
|
||||
key: privKey,
|
||||
headers: headerNames,
|
||||
authorizationHeaderName: "signature",
|
||||
}
|
||||
);
|
||||
|
||||
options.headers = Object.assign(headers, options.headers ?? {});
|
||||
|
||||
return await fetch(url, options);
|
||||
}
|
||||
|
||||
async function processUrl(msg, url, spoiler = false) {
|
||||
let urlObj = new URL(url);
|
||||
let platform = await resolvePlatform(url);
|
||||
|
@ -78,7 +113,7 @@ async function processUrl(msg, url, spoiler = false) {
|
|||
let content, cw, author, timestamp;
|
||||
|
||||
// Fetch post
|
||||
const rawPostData = await fetch(url, {
|
||||
const rawPostData = await signedFetch(url, {
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
Accept: "application/activity+json",
|
||||
|
@ -106,7 +141,7 @@ async function processUrl(msg, url, spoiler = false) {
|
|||
|
||||
// Follow redirect from /object since we need the ID from /notice
|
||||
if (PATH_REGEX.pleroma.test(urlObj.pathname)) {
|
||||
url = await fetch(url, {
|
||||
url = await signedFetch(url, {
|
||||
method: "HEAD",
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
|
@ -157,7 +192,7 @@ async function processUrl(msg, url, spoiler = false) {
|
|||
options
|
||||
)}, ${JSON.stringify(headers)}`
|
||||
);
|
||||
const rawPostData2 = await fetch(
|
||||
const rawPostData2 = await signedFetch(
|
||||
redirUrl,
|
||||
Object.assign(options, {
|
||||
headers: Object.assign(headers, {
|
||||
|
@ -299,12 +334,15 @@ async function processUrl(msg, url, spoiler = false) {
|
|||
}
|
||||
|
||||
// Author data is not sent with the post with AS2
|
||||
const authorData = await fetch(postData.actor ?? postData.attributedTo, {
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
Accept: "application/activity+json",
|
||||
},
|
||||
})
|
||||
const authorData = await signedFetch(
|
||||
postData.actor ?? postData.attributedTo,
|
||||
{
|
||||
headers: {
|
||||
"User-Agent": FRIENDLY_USERAGENT,
|
||||
Accept: "application/activity+json",
|
||||
},
|
||||
}
|
||||
)
|
||||
.then((res) => res.json())
|
||||
.catch((err) => {
|
||||
logger.error("fedimbed", `Failed to get author for "${url}": ${err}`);
|
||||
|
|
Loading…
Reference in a new issue