correctly verify http-signature

This commit is contained in:
lesion 2019-08-02 17:29:55 +02:00
parent 40f7ffa99e
commit 9b2015f46f
5 changed files with 39 additions and 51 deletions

View file

@ -56,7 +56,7 @@
"email-templates": "^6.0.0", "email-templates": "^6.0.0",
"express": "^4.17.1", "express": "^4.17.1",
"express-jwt": "^5.3.1", "express-jwt": "^5.3.1",
"fetch": "^1.1.0", "http-signature": "^1.2.0",
"ics": "^2.15.1", "ics": "^2.15.1",
"inquirer": "^6.5.0", "inquirer": "^6.5.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
@ -65,6 +65,7 @@
"mastodon-api": "lesion/mastodon-api", "mastodon-api": "lesion/mastodon-api",
"morgan": "^1.9.1", "morgan": "^1.9.1",
"multer": "^1.4.2", "multer": "^1.4.2",
"node-fetch": "^2.6.0",
"nuxt": "^2.8.1", "nuxt": "^2.8.1",
"pg": "^7.11.0", "pg": "^7.11.0",
"sass-loader": "^7.1.0", "sass-loader": "^7.1.0",

View file

@ -103,12 +103,12 @@ api.get('/event/:month/:year', eventController.getAll)
// Handle 404 // Handle 404
api.use(function(req, res) { api.use(function(req, res) {
res.send('404: Page not Found', 404) res.status(404).send('404: Page not Found')
}) })
// Handle 500 // Handle 500
api.use(function(error, req, res, next) { api.use(function(error, req, res, next) {
res.send('500: Internal Server Error', 500) res.status(500).send('500: Internal Server Error')
}) })

View file

@ -1,7 +1,10 @@
const fetch = require('fetch') const fetch = require('node-fetch')
const request = require('request') const request = require('request')
const crypto = require('crypto') const crypto = require('crypto')
const config = require('config') const config = require('config')
const httpSignature = require('http-signature')
const actorCache = []
const Helpers = { const Helpers = {
async signAndSend(message, user, to) {//, domain, req, res, targetOrigin) { async signAndSend(message, user, to) {//, domain, req, res, targetOrigin) {
@ -57,24 +60,38 @@ const Helpers = {
} }
}, },
// TODO: cache
// user: les@mastodon.cisti.org
async getFederatedUser(address) { async getFederatedUser(address) {
address = address.trim() address = address.trim()
let [ user, host ] = address.split('@') const [ username, host ] = address.split('@')
const url = `https://${host}/.well-known/webfinger?resource=acct:${user}@${host}` const url = `https://${host}/.well-known/webfinger?resource=acct:${username}@${host}`
console.error('get federated user at => ', address, url) return Helpers.getActor(url)
},
// TODO: cache
async getActor(url, force=false) {
// try with cache first if not forced
if (!force && actorCache[url]) return actorCache[url]
const user = await fetch(url, { headers: {'Accept': 'application/jrd+json, application/json'} }) const user = await fetch(url, { headers: {'Accept': 'application/jrd+json, application/json'} })
.then(res => res.json())
actorCache[url] = user
return user return user
}, },
async verifySignature(req, res) { // ref: https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/
console.error(req.headers['signature']) async verifySignature(req, res, next) {
// https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/ let user = Helpers.getActor(req.body.actor)
const signature_header = req.headers['signature'].split(',')
.map(pair => pair.split('=')) // little hack -> https://github.com/joyent/node-http-signature/pull/83
console.error(signature_header) req.headers.authorization = 'Signature ' + req.headers.signature
return true const parsed = httpSignature.parseRequest(req)
if (httpSignature.verifySignature(parsed, user.publicKey.publicKeyPem)) return next()
// signature not valid, try without cache
user = Helpers.getActor(req.body.actor, true)
if (httpSignature.verifySignature(parsed, user.publicKey.publicKeyPem)) return next()
// still not valid
res.send('Request signature could not be verified', 401)
} }
} }

View file

@ -29,11 +29,7 @@ router.get('/m/:event_id', async (req, res) => {
// get any message coming from federation // get any message coming from federation
// Federation is calling! // Federation is calling!
router.post('/u/:name/inbox', async (req, res) => { router.post('/u/:name/inbox', Helpers.verifySignature, async (req, res) => {
if (!Helpers.verifySignature(req, res)) {
res.send('Request signature could not be verified', 401)
}
const b = req.body const b = req.body
console.error('> INBOX ', b.type, b) console.error('> INBOX ', b.type, b)
@ -55,28 +51,24 @@ router.post('/u/:name/inbox', async (req, res) => {
} }
break break
case 'Announce': case 'Announce':
console.error('This is a boost ?')
Ego.boost(req, res) Ego.boost(req, res)
break break
case 'Note': case 'Note':
console.error('This is a note ! I probably should not receive this') console.error('This is a note ! I probably should not receive this')
break break
case 'Like': case 'Like':
console.error('This is a like!')
Ego.like(req, res) Ego.like(req, res)
break break
case 'Delete': case 'Delete':
console.error('Delete a comment ?!?!') console.error('Delete ?!?!')
break break
case 'Create': case 'Create':
// this is a reply // this is a reply
if (b.object.type === 'Note' && b.object.inReplyTo) { if (b.object.type === 'Note' && b.object.inReplyTo) {
console.error('this is a reply to an event')
Comments.create(b) Comments.create(b)
} else { } else {
console.error('Create what? ', b.object.type) console.error('Create what? ', b.object.type)
} }
break break
} }
}) })

View file

@ -1953,13 +1953,6 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==
biskviit@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/biskviit/-/biskviit-1.0.1.tgz#037a0cd4b71b9e331fd90a1122de17dc49e420a7"
integrity sha1-A3oM1LcbnjMf2QoRIt4X3EnkIKc=
dependencies:
psl "^1.1.7"
bl@^1.0.0: bl@^1.0.0:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c"
@ -3688,13 +3681,6 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
encoding@0.1.12:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=
dependencies:
iconv-lite "~0.4.13"
end-of-stream@^1.0.0, end-of-stream@^1.1.0: end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
@ -4436,14 +4422,6 @@ fast-levenshtein@~2.0.4:
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
fetch@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fetch/-/fetch-1.1.0.tgz#0a8279f06be37f9f0ebb567560a30a480da59a2e"
integrity sha1-CoJ58Gvjf58Ou1Z1YKMKSA2lmi4=
dependencies:
biskviit "1.0.1"
encoding "0.1.12"
figgy-pudding@^3.5.1: figgy-pudding@^3.5.1:
version "3.5.1" version "3.5.1"
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
@ -5306,7 +5284,7 @@ http-proxy@^1.17.0:
follow-redirects "^1.0.0" follow-redirects "^1.0.0"
requires-port "^1.0.0" requires-port "^1.0.0"
http-signature@~1.2.0: http-signature@^1.2.0, http-signature@~1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
@ -5337,7 +5315,7 @@ i18n@^0.8.3:
mustache "*" mustache "*"
sprintf-js ">=1.0.3" sprintf-js ">=1.0.3"
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24" version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@ -8642,7 +8620,7 @@ pseudomap@^1.0.2:
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM=
psl@^1.1.24, psl@^1.1.7: psl@^1.1.24:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6" resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6"
integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA== integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA==