Skip to content

Commit

Permalink
fix: some request properties are not being passed to hawk in Node16
Browse files Browse the repository at this point in the history
Due to nodejs/node#36550 (it was reverted in
Node 14 but it is back in Node 16). req.headers and other properties are
not own properties of requests so they are not cloned.

Node documentation (see discussion on nodejs/node#36550)
advices against clonning the req (or any stream object). This PR fixes that
without modifying the original request object by creating a new object which
prototype is the original request object instead of trying to clone
it.
  • Loading branch information
dafortune committed Feb 25, 2022
1 parent e979df1 commit 799465f
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 26 deletions.
3 changes: 2 additions & 1 deletion .gitignore
@@ -1 +1,2 @@
node_modules/*
node_modules/*
package-lock.json
3 changes: 3 additions & 0 deletions .vscode/settings.json
@@ -0,0 +1,3 @@
{
"editor.formatOnSave": false
}
5 changes: 2 additions & 3 deletions lib/strategy.js
Expand Up @@ -5,8 +5,6 @@ var passport = require('passport'),
util = require('util'),
hawk = require('hawk');

var xtend = require('xtend');

/**
* `Strategy` constructor.
*
Expand Down Expand Up @@ -65,7 +63,8 @@ util.inherits(Strategy, passport.Strategy);
Strategy.prototype.authenticate = function(req, opts) {
//express change req.url when mounting with app.use
//this creates a new request object with url = originalUrl
req = xtend({}, req, { url: req.originalUrl || req.url });
req = Object.create(req);
req.url = req.originalUrl || req.url;

var authenticate = this.bewit ? 'authenticateBewit' : 'authenticate';
hawk.server[authenticate](req, this.verify, opts || {}, function(err, credentials, ext) {
Expand Down
3 changes: 1 addition & 2 deletions package.json
Expand Up @@ -18,8 +18,7 @@
"license": "MIT",
"dependencies": {
"hawk": "jfromaniello/hawk",
"passport": "^0.3.0",
"xtend": "^4.0.1"
"passport": "^0.3.0"
},
"devDependencies": {
"mocha": "^2.3.3",
Expand Down
48 changes: 39 additions & 9 deletions test/bewit.tests.js
@@ -1,6 +1,7 @@
var HawkStrategy = require('../lib/strategy'),
Hawk = require('hawk'),
should = require('should');
should = require('should'),
buildRequest = require('./reqMock').buildRequest;

var credentials = {
key: 'abcd',
Expand All @@ -22,13 +23,13 @@ describe('passport-hawk with bewit', function() {
credentials: credentials,
ttlSec: 60 * 5
});
var req = {
var req = buildRequest({
headers: {
host: 'example.com:8080'
},
method: 'GET',
url: '/resource/4?filter=a&bewit=' + bewit
};
});

strategy.success = function(user) {
user.should.eql('tito');
Expand All @@ -41,18 +42,47 @@ describe('passport-hawk with bewit', function() {
strategy.authenticate(req);
});

it('does not modifies req.url when is available', function (testDone) {
var bewit = Hawk.uri.getBewit(
'http://example.com:8080/resource/4?filter=a',
{
credentials: credentials,
ttlSec: 60 * 5,
}
);
var req = buildRequest({
headers: {
host: 'example.com:8080',
},
method: 'GET',
url: '/abc',
originalUrl: '/resource/4?filter=a&bewit=' + bewit,
});

strategy.success = function (user) {
req.url.should.eql('/abc');

testDone();
};

strategy.error = function () {
testDone(new Error(arguments));
};
strategy.authenticate(req);
});

it('should properly fail with correct challenge code when using different url', function(testDone) {
var bewit = Hawk.uri.getBewit('http://example.com:8080/resource/4?filter=a' + bewit, {
credentials: credentials,
ttlSec: 60 * 5
});
var req = {
var req = buildRequest({
headers: {
host: 'example.com:8080'
},
method: 'GET',
url: '/resource/4?filter=a&bewit=' + bewit
};
});
strategy.error = function(challenge) {
challenge.message.should.eql('Bad mac');
testDone();
Expand All @@ -70,13 +100,13 @@ describe('passport-hawk with bewit', function() {
ttlSec: 60 * 5
});

var req = {
var req = buildRequest({
headers: {
host: 'example.com:8080'
},
method: 'GET',
url: '/resource/4?filter=a&bewit=' + bewit
};
});

strategy.error = function(challenge) {
challenge.message.should.eql('Unknown credentials');
Expand All @@ -87,13 +117,13 @@ describe('passport-hawk with bewit', function() {

it('should call fail when url doesnt have a bewit', function(testDone) {

var req = {
var req = buildRequest({
headers: {
host: 'example.com:8080'
},
method: 'GET',
url: '/resource/4?filter=a'
};
});

strategy.fail = function(failure) {
failure.should.eql('Missing authentication tokens');
Expand Down
23 changes: 12 additions & 11 deletions test/header.tests.js
@@ -1,6 +1,7 @@
var HawkStrategy = require('../lib/strategy'),
Hawk = require('hawk'),
should = require('should');
should = require('should'),
buildRequest = require('./reqMock').buildRequest;;

var credentials = {
key: 'abcd',
Expand All @@ -17,14 +18,14 @@ var strategy = new HawkStrategy(function(id, done) {
describe('passport-hawk', function() {
it('can authenticate a request with a correct header', function(testDone) {
var header = Hawk.client.header('http://example.com:8080/resource/4?filter=a', 'GET', { credentials: credentials });
var req = {
var req = buildRequest({
headers: {
authorization: header.field,
host: 'example.com:8080'
},
method: 'GET',
url: '/resource/4?filter=a'
};
});
strategy.success = function(user) {
user.should.eql('tito');
testDone();
Expand All @@ -34,14 +35,14 @@ describe('passport-hawk', function() {

it('should properly fail with correct challenge code when using different url', function(testDone) {
var header = Hawk.client.header('http://example.com:8080/resource/4?filter=a', 'GET', { credentials: credentials });
var req = {
var req = buildRequest({
headers: {
authorization: header.field,
host: 'example.com:9090'
},
method: 'GET',
url: '/resource/4?filter=a'
};
});
strategy.error = function(challenge) {
challenge.message.should.eql('Bad mac');
testDone();
Expand All @@ -56,14 +57,14 @@ describe('passport-hawk', function() {
algorithm: 'sha256'
}
var authHeader = Hawk.client.header('http://example.com:8080/resource/4?filter=a', 'POST', { credentials: testCredentials });
var req = {
var req = buildRequest({
headers: {
authorization: authHeader.field,
host: 'example.com:8080'
},
method: 'GET',
url: '/resource/4?filter=a'
};
});

strategy.error = function(challenge) {
challenge.message.should.eql('Unknown credentials');
Expand All @@ -74,14 +75,14 @@ describe('passport-hawk', function() {

it('should fail with a stale request', function(testDone) {
var fixedHeader = 'Hawk id="dasd123", ts="1366220539", nonce="xVO62D", mac="9x+7TGN6VLRH8zX5PpwewpIzvf+mTt8m7PDQQW2NU/U="';
var req = {
var req = buildRequest({
headers: {
authorization: fixedHeader,
host: 'example.com:8080'
},
method: 'GET',
url: '/resource/4?filter=a'
};
});
strategy.error = function(challenge) {
challenge.message.should.eql('Stale timestamp');
testDone();
Expand All @@ -91,14 +92,14 @@ describe('passport-hawk', function() {

it('can authenticate a request with options', function(testDone) {
var header = Hawk.client.header('https://example.com/resource/4?filter=a', 'GET', { credentials: credentials });
var req = {
var req = buildRequest({
headers: {
authorization: header.field,
host: 'example.com:3000'
},
method: 'GET',
url: '/resource/4?filter=a'
};
});
var opts = { port: 443 };
strategy.success = function(user) {
user.should.eql('tito');
Expand Down
9 changes: 9 additions & 0 deletions test/reqMock.js
@@ -0,0 +1,9 @@
exports.buildRequest = function buildRequest(reqProps) {
const obj = Object.create({ headers: reqProps.headers });

return Object.assign(obj, {
method: reqProps.method,
url: reqProps.url,
originalUrl: reqProps.originalUrl,
});
};

0 comments on commit 799465f

Please sign in to comment.