diff --git a/common/models/types.ts b/common/models/types.ts index 076eeef88..85dd9a91b 100644 --- a/common/models/types.ts +++ b/common/models/types.ts @@ -43,7 +43,6 @@ export type AuthToken = string; export type MySession = Session & { username?: string; passport?: { user?: number }; - token?: AuthToken; postLoginRedirect?: string; }; diff --git a/server/app.ts b/server/app.ts index a86a82906..7f80cd7c2 100644 --- a/server/app.ts +++ b/server/app.ts @@ -22,6 +22,8 @@ import { initExtractor } from "./infoextractor"; import session, { SessionOptions } from "express-session"; import RedisStore from "connect-redis"; import { setupPostgresMetricsCollection } from "./storage.metrics"; +import cookieparser from "cookie-parser"; +import lusca from "lusca"; const app = express(); @@ -77,6 +79,8 @@ export async function main() { process.on("SIGTERM", shutdown); app.use(metricsMiddleware); + app.use(lusca.csrf()); + app.use(cookieparser(conf.get("session_secret"))); const server = http.createServer(app); async function checkRedis() { if (performance) { diff --git a/server/auth/index.ts b/server/auth/index.ts index 37e61323b..b3d633629 100644 --- a/server/auth/index.ts +++ b/server/auth/index.ts @@ -53,6 +53,8 @@ export async function authTokenMiddleware( if (req.headers.authorization && req.headers.authorization.startsWith("Bearer")) { const token: AuthToken = req.headers.authorization.split(" ")[1]; req.token = token; + } else if (req.cookies?.token) { + req.token = req.cookies.token; } if (!req.token || !(await tokens.validate(req.token))) { @@ -66,8 +68,6 @@ export async function authTokenMiddleware( return; } - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - (req.session as MySession).token = req.token; req.ottsession = await tokens.getSessionInfo(req.token); if (req.ottsession && req.ottsession.isLoggedIn) { try { @@ -87,7 +87,9 @@ router.get("/grant", async (req, res) => { const token: AuthToken = req.headers.authorization.split(" ")[1]; if (await tokens.validate(token)) { log.debug("token is already valid"); - res.json({ + res.cookie("token", token, { + httpOnly: true, + }).json({ token, }); return; @@ -101,7 +103,9 @@ router.get("/grant", async (req, res) => { log.debug("minting new auth token..."); const token: AuthToken = await tokens.mint(); await tokens.setSessionInfo(token, createSession()); - res.json({ + res.cookie("token", token, { + httpOnly: true, + }).json({ token, }); }); @@ -132,8 +136,7 @@ router.get( }); return; } - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - const token = (req.session as MySession).token; + const token = req.cookies?.token; if (!token) { res.status(400).json({ success: false, diff --git a/server/package.json b/server/package.json index 44060bcc5..f1f47a370 100644 --- a/server/package.json +++ b/server/package.json @@ -21,10 +21,12 @@ "axios": "1.6.7", "connect-redis": "7.1.0", "convict": "^6.2.4", + "cookie-parser": "^1.4.6", "dayjs": "^1.10.4", "express": "^4.17.1", "express-session": "^1.17.0", "lodash": "^4.17.21", + "lusca": "^1.7.0", "m3u8-parser": "^6.2.0", "nocache": "^3.0.0", "node-abort-controller": "3.0.1", diff --git a/yarn.lock b/yarn.lock index 02ebb06c1..ce76b1972 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6111,11 +6111,24 @@ convict@^6.2.4: lodash.clonedeep "^4.5.0" yargs-parser "^20.2.7" +cookie-parser@^1.4.6: + version "1.4.6" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.6.tgz#3ac3a7d35a7a03bbc7e365073a26074824214594" + integrity sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA== + dependencies: + cookie "0.4.1" + cookie-signature "1.0.6" + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== +cookie@0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" + integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== + cookie@0.4.2: version "0.4.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" @@ -10475,6 +10488,13 @@ lru-queue@^0.1.0: dependencies: es5-ext "~0.10.2" +lusca@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/lusca/-/lusca-1.7.0.tgz#a5d979f1b51776e60d41e0ca98f886f1b8b95502" + integrity sha512-msnrplCfY7zaqlZBDEloCIKld+RUeMZVeWzSPaGUKeRXFlruNSdKg2XxCyR+zj6BqzcXhXlRnvcvx6rAGgsvMA== + dependencies: + tsscmp "^1.0.5" + lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" @@ -14316,6 +14336,11 @@ tslib@^2.3.1, tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tsscmp@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" + integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== + tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"