diff --git a/e2e/scenario/fixture/api.spec.js b/e2e/scenario/fixture/api.spec.js index 07ab2710..c23c3414 100644 --- a/e2e/scenario/fixture/api.spec.js +++ b/e2e/scenario/fixture/api.spec.js @@ -85,14 +85,14 @@ describe('api', function() { expect(err.status).toBe(403); }); - request.csrf({ - url: restServiceMockUrl + '/form' - }).then(function () { + request.authenticate(new CsrfAuthenticator({ + csrfFetchUrl: restServiceMockUrl + '/form' + })).then(function () { request.post(restServiceMockUrl + '/form').send({ field: 'value' }).do().then(function (res) { expect(res.status).toBe(200); - }).catch(function (err) { + }).catch(function () { expect(true).toBeFalsy(); }); }); diff --git a/e2e/scenario/fixture/mock/apiServiceMock.js b/e2e/scenario/fixture/mock/apiServiceMock.js index 82bf514e..2fdf35e7 100644 --- a/e2e/scenario/fixture/mock/apiServiceMock.js +++ b/e2e/scenario/fixture/mock/apiServiceMock.js @@ -5,6 +5,7 @@ var csrf = require('csurf'); module.exports = function() { var app = express(); + // will also use a _csrf cookie (secret) and validate against it var csrfProtection = csrf({ cookie: true }); @@ -86,9 +87,10 @@ module.exports = function() { app.get('/form', csrfProtection, function (req, res) { if (req.headers['x-csrf-token'].toLowerCase() === 'fetch') { - res.set('x-csrf-token', req.csrfToken()); + var csrfToken = req.csrfToken(); + res.set('x-csrf-token', csrfToken); res.send({ - csrfToken: req.csrfToken() + csrfToken: csrfToken }); } else { res.sendStatus(200); diff --git a/package-lock.json b/package-lock.json index c753c930..11b9a0f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@ui5/uiveri5", - "version": "1.46.1", + "version": "1.37.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -696,58 +696,6 @@ "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", "dev": true }, - "cookie-parser": { - "version": "1.4.5", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", - "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", - "dev": true, - "requires": { - "cookie": "0.4.0", - "cookie-signature": "1.0.6" - }, - "dependencies": { - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true - } - } - }, - "cookie-session": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cookie-session/-/cookie-session-1.4.0.tgz", - "integrity": "sha512-0hhwD+BUIwMXQraiZP/J7VP2YFzqo6g4WqZlWHtEHQ22t0MeZZrNBSCxC1zcaLAs8ApT3BzAKizx9gW/AP9vNA==", - "dev": true, - "requires": { - "cookies": "0.8.0", - "debug": "2.6.9", - "on-headers": "~1.0.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - } - } - }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -759,24 +707,6 @@ "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==" }, - "cookies": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/cookies/-/cookies-0.8.0.tgz", - "integrity": "sha512-8aPsApQfebXnuI+537McwYsDtjVxGm8gTIzQI3FDW6t5t/DAhERxtnbEPN/8RX+uZthoz4eCOgloXaE5cYyNow==", - "dev": true, - "requires": { - "depd": "~2.0.0", - "keygrip": "~1.1.0" - }, - "dependencies": { - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - } - } - }, "core-js": { "version": "2.3.0", "resolved": "http://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz", @@ -800,74 +730,12 @@ "which": "^1.2.9" } }, - "csrf": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csrf/-/csrf-3.1.0.tgz", - "integrity": "sha512-uTqEnCvWRk042asU6JtapDTcJeeailFy4ydOQS28bj1hcLnYRiqi8SsD2jS412AY1I/4qdOwWZun774iqywf9w==", - "dev": true, - "requires": { - "rndm": "1.2.0", - "tsscmp": "1.0.6", - "uid-safe": "2.1.5" - } - }, "cssmin": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/cssmin/-/cssmin-0.3.2.tgz", "integrity": "sha1-3c5MVHtRCuDVlKjx+/iq+OLFwA0=", "dev": true }, - "csurf": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/csurf/-/csurf-1.11.0.tgz", - "integrity": "sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==", - "dev": true, - "requires": { - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "csrf": "3.1.0", - "http-errors": "~1.7.3" - }, - "dependencies": { - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true - }, - "http-errors": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", - "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.4", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - } - } - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -1335,69 +1203,6 @@ } } }, - "express-session": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", - "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", - "dev": true, - "requires": { - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~2.0.0", - "on-headers": "~1.0.2", - "parseurl": "~1.3.3", - "safe-buffer": "5.2.0", - "uid-safe": "~2.1.5" - }, - "dependencies": { - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", - "dev": true - } - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2344,15 +2149,6 @@ } } }, - "keygrip": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", - "integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==", - "dev": true, - "requires": { - "tsscmp": "1.0.6" - } - }, "kuler": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", @@ -2449,15 +2245,6 @@ "signal-exit": "^3.0.0" } }, - "lusca": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/lusca/-/lusca-1.6.1.tgz", - "integrity": "sha512-+JzvUMH/rsE/4XfHdDOl70bip0beRcHSviYATQM0vtls59uVtdn1JMu4iD7ZShBpAmFG8EnaA+PrYG9sECMIOQ==", - "dev": true, - "requires": { - "tsscmp": "^1.0.5" - } - }, "makeerror": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", @@ -3105,12 +2892,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, - "random-bytes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", - "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=", - "dev": true - }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -3289,12 +3070,6 @@ } } }, - "rndm": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/rndm/-/rndm-1.2.0.tgz", - "integrity": "sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=", - "dev": true - }, "run-async": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", @@ -3894,12 +3669,6 @@ "integrity": "sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=", "dev": true }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -3934,12 +3703,6 @@ "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", "dev": true }, - "tsscmp": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", - "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==", - "dev": true - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -3990,15 +3753,6 @@ "integrity": "sha1-S1v/+Rhu/7qoiOTJ6UvZ/EyUkp0=", "dev": true }, - "uid-safe": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", - "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", - "dev": true, - "requires": { - "random-bytes": "~1.0.0" - } - }, "ultron": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", @@ -4328,4 +4082,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/api/csrfAuthenticator.js b/src/api/csrfAuthenticator.js new file mode 100644 index 00000000..d2c40389 --- /dev/null +++ b/src/api/csrfAuthenticator.js @@ -0,0 +1,39 @@ +var logger = require('../logger')(3); + +var CSRF_HEADER = 'x-csrf-token'; + +function CsrfAuthenticator(options){ + options = options || {}; + this.user = options.user; + this.pass = options.pass; + this.csrfHeader = options.csrfHeader; + this.csrfFetchUrl = options.csrfFetchUrl; +} + +CsrfAuthenticator.prototype.authenticate = function () { + var that = this; + if (this.csrfFetchUrl) { + return request.get(this.csrfFetchUrl) + .set(CSRF_HEADER, 'Fetch') + .do() + .then(function (res) { + if (res.headers[CSRF_HEADER]) { + that.csrfHeader = res.headers[CSRF_HEADER]; + } else { + logger.error('Cannot generate CSRF token: missing X-CSRF-Token header'); + } + }).catch(function (err) { + logger.error('Error in generating CSRF token. Details: ' + err); + }); + } +}; + +CsrfAuthenticator.prototype.modifyCall = function (req) { + if (this.csrfHeader) { + req.set(CSRF_HEADER, this.csrfHeader); + } + // superagent will add the cookies e.g. _csrf cookie + return req; +}; + +module.exports = CsrfAuthenticator; diff --git a/src/api/requestPlugin.js b/src/api/requestPlugin.js index d005f1ac..93833476 100644 --- a/src/api/requestPlugin.js +++ b/src/api/requestPlugin.js @@ -1,13 +1,10 @@ var superagent = require('superagent'); -var logger = require('../logger')(3); - -var CSRF_HEADER = 'x-csrf-token'; +var CsrfAuthenticator = require('./csrfAuthenticator'); function RequestPlugin() { } RequestPlugin.prototype.setup = function() { - var that = this; var controlFlow = browser.controlFlow(); var flow = function(superagent) { @@ -19,39 +16,20 @@ RequestPlugin.prototype.setup = function() { }; }; - var csrf = function (options) { - options = options || {}; - if (options.token) { - that.csrfToken = options.token; - } else if (options.url) { - return controlFlow.execute(function () { - return this.get(options.url) - .set(CSRF_HEADER, 'Fetch') - .do() - .then(function (res) { - if (res.headers[CSRF_HEADER]) { - that.csrfToken = res.headers[CSRF_HEADER]; - } else { - logger.error('Cannot generate CSRF token: missing X-CSRF-Token header'); - } - }).catch(function (err) { - logger.error('Error in generating CSRF token. Details: ' + err); - }); - }.bind(this)); - } - }; + var request = superagent.agent().use(flow); - global.request = superagent.agent().use(flow); - - global.request.csrf = csrf; - - var originalPost = global.request.post; - global.request.post = function () { - if (that.csrfToken) { - this.set(CSRF_HEADER, that.csrfToken); - } - return originalPost.apply(this, arguments); + request.authenticate = function (authenticator) { + var originalPost = request.post; + request.post = function () { + authenticator.modifyCall(this); + return originalPost.apply(this, arguments); + }; + + return authenticator.authenticate(); }; + + global.request = request; + global.CsrfAuthenticator = CsrfAuthenticator; }; module.exports = function () {