Authenticate HTTP requests using modern crypto
Authentication means several things in cryptography, but common for them all is to verify the integrity and validity of something. Authentication in regards to messages and requests is that only someone with access to the original secret can verify the message. It is like a signature, but requires a symmetric key, meaning both the party authenticating a message and the party verifying need to share the same key, which must be kept secret.
var authenticatedRequest = require('authenticated-request')
var sodium = require('sodium-native')
// Create secure buffer key in-memory (you probably get this from a file somehow)
var key = authenticatedRequest.keygen()
var authReq = authenticatedRequest([
'Host', 'Date', 'Content-Length', 'Content-Type'
])
var req = {
method: 'POST',
url: 'https://example.com/gateway/upload',
headers: {
host: 'example.com',
accept: 'application/json',
'content-length': '5',
'content-type': 'text/plain',
'date': new Date().toUTCString()
},
payload: Buffer.from('My CV')
}
// Calculate a Message Authentication Code
var mac = authReq.authenticate(key, req)
// This header will be ignored because it is not in the whitelist
// Maybe you want to prefix this with module name and version, and remove that
// information when verifying
finalRequest.headers['authorization'] = mac.toString('base64')
var authenticatedRequest = require('authenticated-request')
var sodium = require('sodium-native')
// Create secure buffer key in-memory (you probably get this from a file somehow)
var key = authenticatedRequest.keygen()
var authReq = authenticatedRequest([
'Host', 'Date', 'Content-Length', 'Content-Type'
])
var req = {
method: 'POST',
url: 'https://example.com/gateway/upload',
headers: {
host: 'example.com',
accept: 'application/json',
'content-length': '5',
'content-type': 'text/plain',
'date': new Date().toUTCString(),
'authorization': 'some long base64 value'
},
payload: Buffer.from('My CV')
}
var mac = Buffer.from(req.headers.authorization, 'base64')
if(!authReq.verify(mac, key, req)) {
throw new Error('MAC did not verify')
}
Canonicalisation means to convert something to a representation where there is no ambiguity whether two statements represent the same value. This module canonicalises HTTP headers by lower casing them and HTTP verbs by upper casing. URLs are up to you to canonicalise. Some things to consider is whether you want to treat URLs as case sensitive, if the order of query parameters matter and whether you want to remove duplicate query parameters or consecutive slashes.
Consider the following urls:
http://example.com/REST//image-server?width=1280&height=720&width=720
http://example.com/rest/image-server?height=720&width=1280
Do they represent the same resource or are they different?
authenticatedRequest.KEYBYTES
- Length in bytes of a valid keyauthenticatedRequest.BYTES
- Length in bytes of a valid MAC
Generate a random key into a optional keyBuf
, or default to allocating a
sodium-native
Secure Buffer. keyBuf
must be at least
authenticatedRequest.KEYBYTES
long.
Returns keyBuf
Create an instance with a whitelist of headers, which must be an array of
strings, that will be included in the Message Authentication Code (MAC) if
passed to authenticate
and verify
. Note that the headers in the whitelist
are optional in the sense that no methods will fail if the exact headers are not
present, but headers not in the whitelist will be ignored. The headers are lower
cased to give them a canonical representation.
Authenticate a request given the following arguments:
key
must be a cryptographically pseudorandom key of lengthauthenticatedRequest.KEYBYTES
passed as a Buffer. It is recommended to usesodium-native
Secure Buffers if possible.- A request object containing:
method
must be a string, and should be a HTTP methodurl
must be a string. Consider whether you deem protocol and hostname part of the url.headers
should be a object ofkey: value
pairs.key
s are lower cased and matched against the whitelist. Headers with anull
value are ignoredpayload
is optional, but must be a Buffer. The default value is the empty Buffer. Can be the HTTP body, a checksum/digest or something else
Returns a message authentication code (prefix MAC) as a Buffer of length
authenticatedRequest.BYTES
Verify the MAC of a request given the following arguments:
mac
must be a Buffer of lengthauthenticatedRequest.BYTES
key
must be a cryptographically pseudorandom key of lengthauthenticatedRequest.KEYBYTES
passed as a Buffer. It is recommended to usesodium-native
Secure Buffers if possible.- A request object containing:
method
must be a string, and should be a HTTP methodurl
must be a string. Consider whether you deem protocol and hostname part of the url.headers
should be a object ofkey: value
pairs.key
s are lower cased and matched against the whitelist. Headers with anull
value are ignoredpayload
is optional, but must be a Buffer. The default value is the empty Buffer. Can be the HTTP body, a checksum/digest or something else
Returns boolean on whether the MAC was valid or not.