diff --git a/package-lock.json b/package-lock.json index 0201a14f05..a6fc49e15e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6934,6 +6934,125 @@ "tslib": "^2.0.0" } }, + "node_modules/@node-saml/node-saml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@node-saml/node-saml/-/node-saml-4.0.5.tgz", + "integrity": "sha512-J5DglElbY1tjOuaR1NPtjOXkXY5bpUhDoKVoeucYN98A3w4fwgjIOPqIGcb6cQsqFq2zZ6vTCeKn5C/hvefSaw==", + "dependencies": { + "@types/debug": "^4.1.7", + "@types/passport": "^1.0.11", + "@types/xml-crypto": "^1.4.2", + "@types/xml-encryption": "^1.2.1", + "@types/xml2js": "^0.4.11", + "@xmldom/xmldom": "^0.8.6", + "debug": "^4.3.4", + "xml-crypto": "^3.0.1", + "xml-encryption": "^3.0.2", + "xml2js": "^0.5.0", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@node-saml/node-saml/node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/@node-saml/node-saml/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@node-saml/node-saml/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/@node-saml/node-saml/node_modules/xml-crypto": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-3.2.0.tgz", + "integrity": "sha512-qVurBUOQrmvlgmZqIVBqmb06TD2a/PpEUfFPgD7BuBfjmoH4zgkqaWSIJrnymlCvM2GGt9x+XtJFA+ttoAufqg==", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "xpath": "0.0.32" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@node-saml/node-saml/node_modules/xml-encryption": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-3.0.2.tgz", + "integrity": "sha512-VxYXPvsWB01/aqVLd6ZMPWZ+qaj0aIdF+cStrVJMcFj3iymwZeI0ABzB3VqMYv48DkSpRhnrXqTUkR34j+UDyg==", + "dependencies": { + "@xmldom/xmldom": "^0.8.5", + "escape-html": "^1.0.3", + "xpath": "0.0.32" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@node-saml/node-saml/node_modules/xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/@node-saml/node-saml/node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@node-saml/node-saml/node_modules/xpath": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", + "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/@node-saml/passport-saml": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@node-saml/passport-saml/-/passport-saml-4.0.4.tgz", + "integrity": "sha512-xFw3gw0yo+K1mzlkW15NeBF7cVpRHN/4vpjmBKzov5YFImCWh/G0LcTZ8krH3yk2/eRPc3Or8LRPudVJBjmYaw==", + "dependencies": { + "@node-saml/node-saml": "^4.0.4", + "@types/express": "^4.17.14", + "@types/passport": "^1.0.11", + "@types/passport-strategy": "^0.2.35", + "passport": "^0.6.0", + "passport-strategy": "^1.0.0" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -13502,13 +13621,22 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "node_modules/@types/passport": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.7.tgz", - "integrity": "sha512-JtswU8N3kxBYgo+n9of7C97YQBT+AYPP2aBfNGTzABqPAZnK/WOAaKfh3XesUYMZRrXFuoPc2Hv0/G/nQFveHw==", + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.15.tgz", + "integrity": "sha512-oHOgzPBp5eLI1U/7421qYV/ZySQXMYCBSfRkDe1tQ0YrIbLY/M/76qIXE7Bs7lFyvw1x5QqiNQ9imvh0fQHe9Q==", "dependencies": { "@types/express": "*" } }, + "node_modules/@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, "node_modules/@types/pg": { "version": "8.6.1", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", @@ -13772,6 +13900,39 @@ "@types/node": "*" } }, + "node_modules/@types/xml-crypto": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@types/xml-crypto/-/xml-crypto-1.4.5.tgz", + "integrity": "sha512-rHc0tlw/ixu7PCqqlpmP9KDIA79IsoV+HFnhJDsdS4MkVAEhBNaazXjv92Xf9oYjWp9e4His4Qzo8fOzoTjT+Q==", + "dependencies": { + "@types/node": "*", + "xpath": "0.0.27" + } + }, + "node_modules/@types/xml-crypto/node_modules/xpath": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", + "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/@types/xml-encryption": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/xml-encryption/-/xml-encryption-1.2.4.tgz", + "integrity": "sha512-I69K/WW1Dv7j6O3jh13z0X8sLWJRXbu5xnHDl9yHzUNDUBtUoBY058eb5s+x/WG6yZC1h8aKdI2EoyEPjyEh+Q==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/xml2js": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.14.tgz", + "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -30573,15 +30734,20 @@ } }, "node_modules/passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", "dependencies": { "passport-strategy": "1.x.x", - "pause": "0.0.1" + "pause": "0.0.1", + "utils-merge": "^1.0.1" }, "engines": { "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" } }, "node_modules/passport-google-oauth20": { @@ -30664,24 +30830,6 @@ "passport-oauth2": "^1.5.0" } }, - "node_modules/passport-saml": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/passport-saml/-/passport-saml-3.2.4.tgz", - "integrity": "sha512-JSgkFXeaexLNQh1RrOvJAgjLnZzH/S3HbX/mWAk+i7aulnjqUe7WKnPl1NPnJWqP7Dqsv0I2Xm6KIFHkftk0HA==", - "deprecated": "For versions >= 4, please use scopped package @node-saml/passport-saml", - "dependencies": { - "@xmldom/xmldom": "^0.7.6", - "debug": "^4.3.2", - "passport-strategy": "^1.0.0", - "xml-crypto": "^2.1.3", - "xml-encryption": "^2.0.0", - "xml2js": "^0.4.23", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">= 12" - } - }, "node_modules/passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", @@ -43472,6 +43620,7 @@ "@contentful/rich-text-types": "^16.0.2", "@google-cloud/bigquery": "^6.0.1", "@node-oauth/oauth2-server": "^4.3.0", + "@node-saml/passport-saml": "^4.0.4", "@overleaf/access-token-encryptor": "*", "@overleaf/fetch-utils": "*", "@overleaf/logger": "*", @@ -43541,13 +43690,12 @@ "otplib": "^12.0.1", "p-limit": "^2.3.0", "parse-data-url": "^2.0.0", - "passport": "^0.4.1", + "passport": "^0.6.0", "passport-google-oauth20": "^2.0.0", "passport-ldapauth": "^2.1.4", "passport-local": "^1.0.0", "passport-oauth2": "^1.5.0", "passport-orcid": "0.0.4", - "passport-saml": "^3.2.4", "passport-twitter": "^1.0.4", "pug": "^3.0.1", "pug-runtime": "^3.0.1", @@ -49454,6 +49602,97 @@ "tslib": "^2.0.0" } }, + "@node-saml/node-saml": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@node-saml/node-saml/-/node-saml-4.0.5.tgz", + "integrity": "sha512-J5DglElbY1tjOuaR1NPtjOXkXY5bpUhDoKVoeucYN98A3w4fwgjIOPqIGcb6cQsqFq2zZ6vTCeKn5C/hvefSaw==", + "requires": { + "@types/debug": "^4.1.7", + "@types/passport": "^1.0.11", + "@types/xml-crypto": "^1.4.2", + "@types/xml-encryption": "^1.2.1", + "@types/xml2js": "^0.4.11", + "@xmldom/xmldom": "^0.8.6", + "debug": "^4.3.4", + "xml-crypto": "^3.0.1", + "xml-encryption": "^3.0.2", + "xml2js": "^0.5.0", + "xmlbuilder": "^15.1.1" + }, + "dependencies": { + "@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "xml-crypto": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-3.2.0.tgz", + "integrity": "sha512-qVurBUOQrmvlgmZqIVBqmb06TD2a/PpEUfFPgD7BuBfjmoH4zgkqaWSIJrnymlCvM2GGt9x+XtJFA+ttoAufqg==", + "requires": { + "@xmldom/xmldom": "^0.8.8", + "xpath": "0.0.32" + } + }, + "xml-encryption": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-3.0.2.tgz", + "integrity": "sha512-VxYXPvsWB01/aqVLd6ZMPWZ+qaj0aIdF+cStrVJMcFj3iymwZeI0ABzB3VqMYv48DkSpRhnrXqTUkR34j+UDyg==", + "requires": { + "@xmldom/xmldom": "^0.8.5", + "escape-html": "^1.0.3", + "xpath": "0.0.32" + } + }, + "xml2js": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + } + } + }, + "xpath": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", + "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==" + } + } + }, + "@node-saml/passport-saml": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@node-saml/passport-saml/-/passport-saml-4.0.4.tgz", + "integrity": "sha512-xFw3gw0yo+K1mzlkW15NeBF7cVpRHN/4vpjmBKzov5YFImCWh/G0LcTZ8krH3yk2/eRPc3Or8LRPudVJBjmYaw==", + "requires": { + "@node-saml/node-saml": "^4.0.4", + "@types/express": "^4.17.14", + "@types/passport": "^1.0.11", + "@types/passport-strategy": "^0.2.35", + "passport": "^0.6.0", + "passport-strategy": "^1.0.0" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -52099,6 +52338,7 @@ "@lezer/lr": "^1.3.13", "@lezer/markdown": "^1.1.0", "@node-oauth/oauth2-server": "^4.3.0", + "@node-saml/passport-saml": "^4.0.4", "@opentelemetry/api": "^1.4.1", "@opentelemetry/auto-instrumentations-web": "^0.33.1", "@opentelemetry/context-zone": "^1.15.2", @@ -52280,13 +52520,12 @@ "otplib": "^12.0.1", "p-limit": "^2.3.0", "parse-data-url": "^2.0.0", - "passport": "^0.4.1", + "passport": "^0.6.0", "passport-google-oauth20": "^2.0.0", "passport-ldapauth": "^2.1.4", "passport-local": "^1.0.0", "passport-oauth2": "^1.5.0", "passport-orcid": "0.0.4", - "passport-saml": "^3.2.4", "passport-twitter": "^1.0.4", "pdfjs-dist213": "npm:pdfjs-dist@2.13.216", "pdfjs-dist401": "npm:pdfjs-dist@4.0.189", @@ -56786,13 +57025,22 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "@types/passport": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.7.tgz", - "integrity": "sha512-JtswU8N3kxBYgo+n9of7C97YQBT+AYPP2aBfNGTzABqPAZnK/WOAaKfh3XesUYMZRrXFuoPc2Hv0/G/nQFveHw==", + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.15.tgz", + "integrity": "sha512-oHOgzPBp5eLI1U/7421qYV/ZySQXMYCBSfRkDe1tQ0YrIbLY/M/76qIXE7Bs7lFyvw1x5QqiNQ9imvh0fQHe9Q==", "requires": { "@types/express": "*" } }, + "@types/passport-strategy": { + "version": "0.2.38", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.38.tgz", + "integrity": "sha512-GC6eMqqojOooq993Tmnmp7AUTbbQSgilyvpCYQjT+H6JfG/g6RGc7nXEniZlp0zyKJ0WUdOiZWLBZft9Yug1uA==", + "requires": { + "@types/express": "*", + "@types/passport": "*" + } + }, "@types/pg": { "version": "8.6.1", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.1.tgz", @@ -57056,6 +57304,38 @@ "@types/node": "*" } }, + "@types/xml-crypto": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@types/xml-crypto/-/xml-crypto-1.4.5.tgz", + "integrity": "sha512-rHc0tlw/ixu7PCqqlpmP9KDIA79IsoV+HFnhJDsdS4MkVAEhBNaazXjv92Xf9oYjWp9e4His4Qzo8fOzoTjT+Q==", + "requires": { + "@types/node": "*", + "xpath": "0.0.27" + }, + "dependencies": { + "xpath": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", + "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==" + } + } + }, + "@types/xml-encryption": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/xml-encryption/-/xml-encryption-1.2.4.tgz", + "integrity": "sha512-I69K/WW1Dv7j6O3jh13z0X8sLWJRXbu5xnHDl9yHzUNDUBtUoBY058eb5s+x/WG6yZC1h8aKdI2EoyEPjyEh+Q==", + "requires": { + "@types/node": "*" + } + }, + "@types/xml2js": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.14.tgz", + "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==", + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -71010,12 +71290,13 @@ } }, "passport": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.4.1.tgz", - "integrity": "sha512-IxXgZZs8d7uFSt3eqNjM9NQ3g3uQCW5avD8mRNoXV99Yig50vjuaez6dQK2qC0kVWPRTujxY0dWgGfT09adjYg==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", "requires": { "passport-strategy": "1.x.x", - "pause": "0.0.1" + "pause": "0.0.1", + "utils-merge": "^1.0.1" } }, "passport-google-oauth20": { @@ -71075,20 +71356,6 @@ "passport-oauth2": "^1.5.0" } }, - "passport-saml": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/passport-saml/-/passport-saml-3.2.4.tgz", - "integrity": "sha512-JSgkFXeaexLNQh1RrOvJAgjLnZzH/S3HbX/mWAk+i7aulnjqUe7WKnPl1NPnJWqP7Dqsv0I2Xm6KIFHkftk0HA==", - "requires": { - "@xmldom/xmldom": "^0.7.6", - "debug": "^4.3.2", - "passport-strategy": "^1.0.0", - "xml-crypto": "^2.1.3", - "xml-encryption": "^2.0.0", - "xml2js": "^0.4.23", - "xmlbuilder": "^15.1.1" - } - }, "passport-strategy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", diff --git a/services/web/app/src/Features/Authentication/AuthenticationController.js b/services/web/app/src/Features/Authentication/AuthenticationController.js index 3ad4709032..56db9e8f89 100644 --- a/services/web/app/src/Features/Authentication/AuthenticationController.js +++ b/services/web/app/src/Features/Authentication/AuthenticationController.js @@ -80,30 +80,36 @@ const AuthenticationController = { // This function is middleware which wraps the passport.authenticate middleware, // so we can send back our custom `{message: {text: "", type: ""}}` responses on failure, // and send a `{redir: ""}` response on success - passport.authenticate('local', function (err, user, info) { - if (err) { - return next(err) - } - if (user) { - // `user` is either a user object or false - AuthenticationController.setAuditInfo(req, { method: 'Password login' }) - return AuthenticationController.finishLogin(user, req, res, next) - } else { - if (info.redir != null) { - return res.json({ redir: info.redir }) + passport.authenticate( + 'local', + { keepSessionInfo: true }, + function (err, user, info) { + if (err) { + return next(err) + } + if (user) { + // `user` is either a user object or false + AuthenticationController.setAuditInfo(req, { + method: 'Password login', + }) + return AuthenticationController.finishLogin(user, req, res, next) } else { - res.status(info.status || 200) - delete info.status - const body = { message: info } - const { errorReason } = info - if (errorReason) { - body.errorReason = errorReason - delete info.errorReason + if (info.redir != null) { + return res.json({ redir: info.redir }) + } else { + res.status(info.status || 200) + delete info.status + const body = { message: info } + const { errorReason } = info + if (errorReason) { + body.errorReason = errorReason + delete info.errorReason + } + return res.json(body) } - return res.json(body) } } - })(req, res, next) + )(req, res, next) }, finishLogin(user, req, res, next) { @@ -557,55 +563,34 @@ const AuthenticationController = { } function _afterLoginSessionSetup(req, user, callback) { - if (callback == null) { - callback = function () {} - } - req.login(user, function (err) { + req.login(user, { keepSessionInfo: true }, function (err) { if (err) { OError.tag(err, 'error from req.login', { user_id: user._id, }) return callback(err) } - // Regenerate the session to get a new sessionID (cookie value) to - // protect against session fixation attacks - const oldSession = req.session - req.session.destroy(function (err) { + delete req.session.__tmp + delete req.session.csrfSecret + req.session.save(function (err) { if (err) { - OError.tag(err, 'error when trying to destroy old session', { + OError.tag(err, 'error saving regenerated session after login', { user_id: user._id, }) return callback(err) } - req.sessionStore.generate(req) - // Note: the validation token is not writable, so it does not get - // transferred to the new session below. - for (const key in oldSession) { - const value = oldSession[key] - if (key !== '__tmp' && key !== 'csrfSecret') { - req.session[key] = value - } + UserSessionsManager.trackSession(user, req.sessionID, function () {}) + if (!req.deviceHistory) { + // Captcha disabled or SSO-based login. + return callback() } - req.session.save(function (err) { - if (err) { - OError.tag(err, 'error saving regenerated session after login', { - user_id: user._id, - }) - return callback(err) - } - UserSessionsManager.trackSession(user, req.sessionID, function () {}) - if (!req.deviceHistory) { - // Captcha disabled or SSO-based login. - return callback() - } - req.deviceHistory.add(user.email) - req.deviceHistory - .serialize(req.res) - .catch(err => { - logger.err({ err }, 'cannot serialize deviceHistory') - }) - .finally(() => callback()) - }) + req.deviceHistory.add(user.email) + req.deviceHistory + .serialize(req.res) + .catch(err => { + logger.err({ err }, 'cannot serialize deviceHistory') + }) + .finally(() => callback()) }) }) } diff --git a/services/web/app/src/Features/User/UserController.js b/services/web/app/src/Features/User/UserController.js index f2a6070f50..d557c85c84 100644 --- a/services/web/app/src/Features/User/UserController.js +++ b/services/web/app/src/Features/User/UserController.js @@ -266,7 +266,8 @@ async function tryDeleteUser(req, res, next) { const sessionId = req.sessionID if (typeof req.logout === 'function') { - req.logout() + const logout = promisify(req.logout) + await logout() } const destroySession = promisify(req.session.destroy.bind(req.session)) @@ -431,9 +432,10 @@ async function doLogout(req) { logger.debug({ user }, 'logging out') const sessionId = req.sessionID - // passport logout if (typeof req.logout === 'function') { - req.logout() + // passport logout + const logout = promisify(req.logout.bind(req)) + await logout() } const destroySession = promisify(req.session.destroy.bind(req.session)) diff --git a/services/web/package.json b/services/web/package.json index 1777a9f5e8..b5d2dbcac5 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -68,6 +68,7 @@ "@contentful/rich-text-types": "^16.0.2", "@google-cloud/bigquery": "^6.0.1", "@node-oauth/oauth2-server": "^4.3.0", + "@node-saml/passport-saml": "^4.0.4", "@overleaf/access-token-encryptor": "*", "@overleaf/fetch-utils": "*", "@overleaf/logger": "*", @@ -137,13 +138,12 @@ "otplib": "^12.0.1", "p-limit": "^2.3.0", "parse-data-url": "^2.0.0", - "passport": "^0.4.1", + "passport": "^0.6.0", "passport-google-oauth20": "^2.0.0", "passport-ldapauth": "^2.1.4", "passport-local": "^1.0.0", "passport-oauth2": "^1.5.0", "passport-orcid": "0.0.4", - "passport-saml": "^3.2.4", "passport-twitter": "^1.0.4", "pug": "^3.0.1", "pug-runtime": "^3.0.1", diff --git a/services/web/test/unit/src/Authentication/AuthenticationControllerTests.js b/services/web/test/unit/src/Authentication/AuthenticationControllerTests.js index 15bd16199f..cc0b08cbf5 100644 --- a/services/web/test/unit/src/Authentication/AuthenticationControllerTests.js +++ b/services/web/test/unit/src/Authentication/AuthenticationControllerTests.js @@ -77,7 +77,7 @@ describe('AuthenticationController', function () { '../User/UserSessionsManager': (this.UserSessionsManager = { trackSession: sinon.stub(), untrackSession: sinon.stub(), - revokeAllUserSessions: sinon.stub().callsArgWith(1, null), + revokeAllUserSessions: sinon.stub().yields(null), }), '../../infrastructure/Modules': (this.Modules = { hooks: { fire: sinon.stub().yields(null, []) }, @@ -184,17 +184,17 @@ describe('AuthenticationController', function () { describe('passportLogin', function () { beforeEach(function () { this.info = null - this.req.login = sinon.stub().callsArgWith(1, null) + this.req.login = sinon.stub().yields(null) this.res.json = sinon.stub() this.req.session = { passport: { user: this.user }, postLoginRedirect: '/path/to/redir/to', } - this.req.session.destroy = sinon.stub().callsArgWith(0, null) - this.req.session.save = sinon.stub().callsArgWith(0, null) + this.req.session.destroy = sinon.stub().yields(null) + this.req.session.save = sinon.stub().yields(null) this.req.sessionStore = { generate: sinon.stub() } this.AuthenticationController.finishLogin = sinon.stub() - this.passport.authenticate.callsArgWith(1, null, this.user, this.info) + this.passport.authenticate.yields(null, this.user, this.info) this.err = new Error('woops') }) @@ -205,7 +205,7 @@ describe('AuthenticationController', function () { describe('when authenticate produces an error', function () { beforeEach(function () { - this.passport.authenticate.callsArgWith(1, this.err) + this.passport.authenticate.yields(this.err) }) it('should return next with an error', function () { @@ -221,7 +221,7 @@ describe('AuthenticationController', function () { describe('when authenticate produces a user', function () { beforeEach(function () { this.req.session.postLoginRedirect = 'some_redirect' - this.passport.authenticate.callsArgWith(1, null, this.user, this.info) + this.passport.authenticate.yields(null, this.user, this.info) }) afterEach(function () { @@ -244,7 +244,7 @@ describe('AuthenticationController', function () { describe('when authenticate does not produce a user', function () { beforeEach(function () { this.info = { text: 'a', type: 'b' } - this.passport.authenticate.callsArgWith(1, null, false, this.info) + this.passport.authenticate.yields(null, false, this.info) }) it('should not call finishLogin', function () { @@ -273,8 +273,7 @@ describe('AuthenticationController', function () { beforeEach(function () { this.AuthenticationController._recordFailedLogin = sinon.stub() this.AuthenticationController._recordSuccessfulLogin = sinon.stub() - this.Modules.hooks.fire = sinon.stub().callsArgWith(3, null, []) - // @AuthenticationController.establishUserSession = sinon.stub().callsArg(2) + this.Modules.hooks.fire = sinon.stub().yields(null, []) this.req.body = { email: this.email, password: this.password, @@ -290,7 +289,7 @@ describe('AuthenticationController', function () { beforeEach(function () { this.Modules.hooks.fire = sinon .stub() - .callsArgWith(3, null, [null, { redir: '/somewhere' }, null]) + .yields(null, [null, { redir: '/somewhere' }, null]) }) it('should stop early and call done with this info object', function (done) { @@ -311,7 +310,7 @@ describe('AuthenticationController', function () { describe('when the users rate limit', function () { beforeEach(function () { - this.LoginRateLimiter.processLoginRequest.callsArgWith(1, null, false) + this.LoginRateLimiter.processLoginRequest.yields(null, false) }) it('should block the request if the limit has been exceeded', function (done) { @@ -330,10 +329,10 @@ describe('AuthenticationController', function () { describe('when the user is authenticated', function () { beforeEach(function () { this.cb = sinon.stub() - this.LoginRateLimiter.processLoginRequest.callsArgWith(1, null, true) + this.LoginRateLimiter.processLoginRequest.yields(null, true) this.AuthenticationManager.authenticate = sinon .stub() - .callsArgWith(3, null, this.user) + .yields(null, this.user) this.req.sessionID = Math.random() }) @@ -361,7 +360,7 @@ describe('AuthenticationController', function () { beforeEach(function () { this.AuthenticationManager.authenticate = sinon .stub() - .callsArgWith(3, new AuthenticationErrors.ParallelLoginError()) + .yields(new AuthenticationErrors.ParallelLoginError()) this.AuthenticationController.doPassportLogin( this.req, this.req.body.email, @@ -437,10 +436,10 @@ describe('AuthenticationController', function () { describe('when the user is not authenticated', function () { beforeEach(function () { - this.LoginRateLimiter.processLoginRequest.callsArgWith(1, null, true) + this.LoginRateLimiter.processLoginRequest.yields(null, true) this.AuthenticationManager.authenticate = sinon .stub() - .callsArgWith(3, null, null) + .yields(null, null) this.cb = sinon.stub() this.AuthenticationController.doPassportLogin( this.req, @@ -937,7 +936,7 @@ describe('AuthenticationController', function () { describe('_recordSuccessfulLogin', function () { beforeEach(function () { - this.UserUpdater.updateUser = sinon.stub().callsArg(2) + this.UserUpdater.updateUser = sinon.stub().yields() this.AuthenticationController._recordSuccessfulLogin( this.user._id, this.callback @@ -1078,8 +1077,8 @@ describe('AuthenticationController', function () { this.req.session = { passport: { user: { _id: 'one' } }, } - this.req.session.destroy = sinon.stub().callsArgWith(0, null) - this.req.session.save = sinon.stub().callsArgWith(0, null) + this.req.session.destroy = sinon.stub().yields(null) + this.req.session.save = sinon.stub().yields(null) this.req.sessionStore = { generate: sinon.stub() } this.req.login = sinon.stub().yields(null) @@ -1345,9 +1344,7 @@ describe('AuthenticationController', function () { describe('when req.session.save produces an error', function () { beforeEach(function () { - this.req.session.save = sinon - .stub() - .callsArgWith(0, new Error('woops')) + this.req.session.save = sinon.stub().yields(new Error('woops')) }) it('should produce an error', function (done) { diff --git a/services/web/test/unit/src/User/UserControllerTests.js b/services/web/test/unit/src/User/UserControllerTests.js index d6b4f86333..8409163aa1 100644 --- a/services/web/test/unit/src/User/UserControllerTests.js +++ b/services/web/test/unit/src/User/UserControllerTests.js @@ -173,7 +173,7 @@ describe('UserController', function () { describe('tryDeleteUser', function () { beforeEach(function () { this.req.body.password = 'wat' - this.req.logout = sinon.stub() + this.req.logout = sinon.stub().yields() this.req.session.destroy = sinon.stub().yields() this.SessionManager.getLoggedInUserId = sinon .stub()