Force signed headers in http signatures
Thanks Roger
This commit is contained in:
parent
2a9562fc58
commit
797d05bdd9
4 changed files with 39 additions and 3 deletions
|
@ -50,7 +50,11 @@ function isHTTPSignatureVerified (httpSignatureParsed: any, actor: MActor): bool
|
|||
}
|
||||
|
||||
function parseHTTPSignature (req: Request, clockSkew?: number) {
|
||||
return httpSignature.parse(req, { clockSkew })
|
||||
const headers = req.method === 'POST'
|
||||
? HTTP_SIGNATURE.REQUIRED_HEADERS.POST
|
||||
: HTTP_SIGNATURE.REQUIRED_HEADERS.ALL
|
||||
|
||||
return httpSignature.parse(req, { clockSkew, headers })
|
||||
}
|
||||
|
||||
// JSONLD
|
||||
|
|
|
@ -513,6 +513,10 @@ const HTTP_SIGNATURE = {
|
|||
HEADER_NAME: 'signature',
|
||||
ALGORITHM: 'rsa-sha256',
|
||||
HEADERS_TO_SIGN: [ '(request-target)', 'host', 'date', 'digest' ],
|
||||
REQUIRED_HEADERS: {
|
||||
ALL: [ '(request-target)', 'host', 'date' ],
|
||||
POST: [ '(request-target)', 'host', 'date', 'digest' ]
|
||||
},
|
||||
CLOCK_SKEW_SECONDS: 1800
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,16 @@ async function checkHttpSignature (req: Request, res: Response) {
|
|||
const sig = req.headers[HTTP_SIGNATURE.HEADER_NAME] as string
|
||||
if (sig && sig.startsWith('Signature ') === true) req.headers[HTTP_SIGNATURE.HEADER_NAME] = sig.replace(/^Signature /, '')
|
||||
|
||||
const parsed = parseHTTPSignature(req, HTTP_SIGNATURE.CLOCK_SKEW_SECONDS)
|
||||
let parsed: any
|
||||
|
||||
try {
|
||||
parsed = parseHTTPSignature(req, HTTP_SIGNATURE.CLOCK_SKEW_SECONDS)
|
||||
} catch (err) {
|
||||
logger.warn('Invalid signature because of exception in signature parser', { reqBody: req.body, err })
|
||||
|
||||
res.status(403).json({ error: err.message })
|
||||
return false
|
||||
}
|
||||
|
||||
const keyId = parsed.keyId
|
||||
if (!keyId) {
|
||||
|
|
|
@ -99,13 +99,32 @@ describe('Test ActivityPub security', function () {
|
|||
expect(response.statusCode).to.equal(403)
|
||||
})
|
||||
|
||||
it('Should succeed with a valid HTTP signature', async function () {
|
||||
it('Should reject requests without appropriate signed headers', async function () {
|
||||
await setKeysOfServer(servers[0], servers[1], keys.publicKey, keys.privateKey)
|
||||
await setKeysOfServer(servers[1], servers[1], keys.publicKey, keys.privateKey)
|
||||
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
|
||||
const headers = buildGlobalHeaders(body)
|
||||
|
||||
const signatureOptions = baseHttpSignature()
|
||||
const badHeadersMatrix = [
|
||||
[ '(request-target)', 'date', 'digest' ],
|
||||
[ 'host', 'date', 'digest' ],
|
||||
[ '(request-target)', 'host', 'digest' ]
|
||||
]
|
||||
|
||||
for (const badHeaders of badHeadersMatrix) {
|
||||
signatureOptions.headers = badHeaders
|
||||
|
||||
const { response } = await makePOSTAPRequest(url, body, signatureOptions, headers)
|
||||
expect(response.statusCode).to.equal(403)
|
||||
}
|
||||
})
|
||||
|
||||
it('Should succeed with a valid HTTP signature', async function () {
|
||||
const body = activityPubContextify(getAnnounceWithoutContext(servers[1]))
|
||||
const headers = buildGlobalHeaders(body)
|
||||
|
||||
const { response } = await makePOSTAPRequest(url, body, baseHttpSignature(), headers)
|
||||
|
||||
expect(response.statusCode).to.equal(204)
|
||||
|
|
Loading…
Reference in a new issue