Skip to content

Commit

Permalink
Add support for created and expires values (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
blacktemplar committed Apr 20, 2020
1 parent 88b5740 commit 4fda5d0
Show file tree
Hide file tree
Showing 3 changed files with 307 additions and 11 deletions.
50 changes: 47 additions & 3 deletions lib/parser.js
Expand Up @@ -23,7 +23,8 @@ var ParamsState = {
Name: 0,
Quote: 1,
Value: 2,
Comma: 3
Comma: 3,
Number: 4
};

///--- Specific Errors
Expand Down Expand Up @@ -180,7 +181,13 @@ module.exports = {
tmpValue = '';
substate = ParamsState.Value;
} else {
throw new InvalidHeaderError('bad param format');
//number
substate = ParamsState.Number;
code = c.charCodeAt(0);
if (code < 0x30 || code > 0x39) { //character not in 0-9
throw new InvalidHeaderError('bad param format');
}
tmpValue = c;
}
break;

Expand All @@ -193,6 +200,21 @@ module.exports = {
}
break;

case ParamsState.Number:
if (c === ',') {
parsed.params[tmpName] = parseInt(tmpValue, 10);
tmpName = '';
substate = ParamsState.Name;
} else {
code = c.charCodeAt(0);
if (code < 0x30 || code > 0x39) { //character not in 0-9
throw new InvalidHeaderError('bad param format');
}
tmpValue += c;
}
break;


case ParamsState.Comma:
if (c === ',') {
tmpName = '';
Expand Down Expand Up @@ -280,6 +302,10 @@ module.exports = {
authzHeaderName + ' header');
}
parsed.signingString += '(opaque): ' + opaque;
} else if (h === '(created)') {
parsed.signingString += '(created): ' + parsed.params.created;
} else if (h === '(expires)') {
parsed.signingString += '(expires): ' + parsed.params.expires;
} else {
var value = request.headers[h];
if (value === undefined)
Expand All @@ -293,14 +319,15 @@ module.exports = {

// Check against the constraints
var date;
var skew;
if (request.headers.date || request.headers['x-date']) {
if (request.headers['x-date']) {
date = new Date(request.headers['x-date']);
} else {
date = new Date(request.headers.date);
}
var now = new Date();
var skew = Math.abs(now.getTime() - date.getTime());
skew = Math.abs(now.getTime() - date.getTime());

if (skew > options.clockSkew * 1000) {
throw new ExpiredRequestError('clock skew of ' +
Expand All @@ -310,6 +337,23 @@ module.exports = {
}
}

if (parsed.params.created) {
skew = parsed.params.created - Math.floor(Date.now() / 1000);
if (skew > options.clockSkew) {
throw new ExpiredRequestError('Created lies in the future (with ' +
'skew ' + skew + 's greater than allowed ' + options.clockSkew +
's');
}
}

if (parsed.params.expires) {
var expiredSince = Math.floor(Date.now() / 1000) - parsed.params.expires;
if (expiredSince > options.clockSkew) {
throw new ExpiredRequestError('Request expired with skew ' +
expiredSince + 's greater than allowed ' + options.clockSkew + 's');
}
}

headers.forEach(function (hdr) {
// Remember that we already checked any headers in the params
// were in the request, so if this passes we're good.
Expand Down
39 changes: 31 additions & 8 deletions lib/signer.js
Expand Up @@ -17,7 +17,8 @@ var validateAlgorithm = utils.validateAlgorithm;

///--- Globals

var AUTHZ_PARAMS = [ 'keyId', 'algorithm', 'opaque', 'headers', 'signature' ];
var AUTHZ_PARAMS = [ 'keyId', 'algorithm', 'created', 'expires', 'opaque',
'headers', 'signature' ];

///--- Specific Errors

Expand All @@ -41,9 +42,13 @@ function FormatAuthz(prefix, params) {
var value = params[param];
if (value === undefined)
continue;
assert.string(value, 'params.' + param);
if (typeof (value) === 'number') {
authz += prefix + sprintf('%s=%d', param, value);
} else {
assert.string(value, 'params.' + param);

authz += prefix + sprintf('%s="%s"', param, value);
authz += prefix + sprintf('%s="%s"', param, value);
}
prefix = ',';
}

Expand Down Expand Up @@ -294,6 +299,9 @@ module.exports = {
* signing algorithm for the type of key given
* - {String} httpVersion optional; defaults to '1.1'.
* - {Boolean} strict optional; defaults to 'false'.
* - {int} expiresIn optional; defaults to 60. The
* seconds after which the signature should
* expire;
* @return {Boolean} true if Authorization (and optionally Date) were added.
* @throws {TypeError} on bad parameter types (input).
* @throws {InvalidAlgorithmError} if algorithm was bad or incompatible with
Expand All @@ -310,6 +318,7 @@ module.exports = {
assert.optionalString(options.opaque, 'options.opaque');
assert.optionalArrayOfString(options.headers, 'options.headers');
assert.optionalString(options.httpVersion, 'options.httpVersion');
assert.optionalNumber(options.expiresIn, 'options.expiresIn');

if (!request.getHeader('Date'))
request.setHeader('Date', jsprim.rfc1123(new Date()));
Expand Down Expand Up @@ -355,6 +364,11 @@ module.exports = {
options.algorithm = alg[0] + '-' + alg[1];
}

var params = {
'keyId': options.keyId,
'algorithm': options.algorithm
};

var i;
var stringToSign = '';
for (i = 0; i < headers.length; i++) {
Expand Down Expand Up @@ -391,6 +405,18 @@ module.exports = {
throw new MissingHeaderError('options.opaque was not in the request');
}
stringToSign += '(opaque): ' + opaque;
} else if (h === '(created)') {
var created = Math.floor(Date.now() / 1000);
params.created = created;
stringToSign += '(created): ' + created;
} else if (h === '(expires)') {
var expiresIn = options.expiresIn;
if (expiresIn === undefined) {
expiresIn = 60;
}
const expires = Math.floor(Date.now() / 1000) + expiresIn;
params.expires = expires;
stringToSign += '(expires): ' + expires;
} else {
var value = request.getHeader(h);
if (value === undefined || value === '') {
Expand Down Expand Up @@ -431,11 +457,8 @@ module.exports = {
var prefix = authzHeaderName.toLowerCase() === utils.HEADER.SIG ?
'' : 'Signature ';

var params = {
'keyId': options.keyId,
'algorithm': options.algorithm,
'signature': signature
};
params.signature = signature;

if (options.opaque)
params.opaque = options.opaque;
if (options.headers)
Expand Down

0 comments on commit 4fda5d0

Please sign in to comment.