Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for created and expires values #110

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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