diff --git a/src/api/oauth/auth.ts b/src/api/oauth/auth.ts index dbcce8d..ec513c3 100644 --- a/src/api/oauth/auth.ts +++ b/src/api/oauth/auth.ts @@ -12,6 +12,8 @@ import { ObjectID } from "bson"; const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Response) => { let { response_type, client_id, redirect_uri, scope, state, nored } = req.query; const sendError = (type) => { + if (redirect_uri === "$local") + redirect_uri = "/code"; res.redirect(redirect_uri += `?error=${type}&state=${state}`); } /** @@ -63,7 +65,9 @@ const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Res }); await ClientCode.save(code); - let ruri = client.redirect_url + `?code=${code.code}&state=${state}`; + let redir = client.redirect_url === "$local" ? "/code" : client.redirect_url; + + let ruri = redir + `?code=${code.code}&state=${state}`; if (nored === "true") { res.json({ redirect_uri: ruri diff --git a/src/api/oauth/refresh.ts b/src/api/oauth/refresh.ts index ccea5ce..84d6648 100644 --- a/src/api/oauth/refresh.ts +++ b/src/api/oauth/refresh.ts @@ -13,12 +13,24 @@ import { JWTExpDur } from "../../keys"; import RefreshToken from "../../models/refresh_token"; import { getEncryptionKey } from "../../helper/user_key"; +// TODO: +/* +For example, the authorization server could employ refresh token +rotation in which a new refresh token is issued with every access +token refresh response. The previous refresh token is invalidated but retained by the authorization server. If a refresh token is +compromised and subsequently used by both the attacker and the +legitimate client, one of them will present an invalidated refresh +token, which will inform the authorization server of the breach. +*/ + +const refreshTokenValidTime = moment.duration(6, "month"); + const RefreshTokenRoute = Stacker(GetClientAuthMiddleware(false, false, true), async (req: Request, res: Response) => { let grant_type = req.query.grant_type || req.body.grant_type; if (!grant_type || grant_type === "authorization_code") { let code = req.query.code || req.body.code; let c = await ClientCode.findOne({ code: code }) - if (!c) { + if (!c || moment(c.validTill).isBefore()) { throw new RequestError(req.__("Invalid code"), HttpStatusCode.BAD_REQUEST); } @@ -33,7 +45,7 @@ const RefreshTokenRoute = Stacker(GetClientAuthMiddleware(false, false, true), a permissions: c.permissions, token: randomBytes(16).toString("hex"), valid: true, - validTill: moment().add(6, "months").toDate() + validTill: moment().add(refreshTokenValidTime).toDate() }); await RefreshToken.save(token); await ClientCode.delete(c); @@ -63,7 +75,11 @@ const RefreshTokenRoute = Stacker(GetClientAuthMiddleware(false, false, true), a if (!refresh_token) throw new RequestError(req.__("refresh_token not set"), HttpStatusCode.BAD_REQUEST); let token = await RefreshToken.findOne({ token: refresh_token }); - if (!token) throw new RequestError(req.__("Invalid token"), HttpStatusCode.BAD_REQUEST); + if (!token || !token.valid || moment(token.validTill).isBefore()) + throw new RequestError(req.__("Invalid token"), HttpStatusCode.BAD_REQUEST); + + token.validTill = moment().add(refreshTokenValidTime).toDate(); + await RefreshToken.save(token); let user = await User.findById(token.user); let client = await Client.findById(token.client) diff --git a/src/views/views.ts b/src/views/views.ts index f3f1541..104966e 100644 --- a/src/views/views.ts +++ b/src/views/views.ts @@ -1,111 +1,119 @@ -import { Router, IRouter, Request } from "express" -import GetLoginPage from "./login"; -import GetAuthPage from "./authorize"; -import promiseMiddleware from "../helper/promiseMiddleware"; -import config from "../config"; -import * as Handlebars from "handlebars"; -import GetRegistrationPage from "./register"; -import GetAdminPage from "./admin"; -import { HttpStatusCode } from "../helper/request_error"; -import * as moment from "moment"; -import Permission, { IPermission } from "../models/permissions"; -import Client from "../models/client"; -import { Logging } from "@hibas123/nodelogging"; -import Stacker from "../api/middlewares/stacker"; -import { UserMiddleware, GetUserMiddleware } from "../api/middlewares/user"; -// import GetUserPage from "./user"; - -Handlebars.registerHelper("appname", () => config.core.name); - -const cacheTime = config.core.dev ? moment.duration(1, "month").asSeconds() : 10; - -const ViewRouter: IRouter = Router(); -ViewRouter.get("/", UserMiddleware, (req, res) => { - res.send("This is the main page") -}) - -ViewRouter.get("/register", (req, res) => { - res.setHeader("Cache-Control", "public, max-age=" + cacheTime); - res.send(GetRegistrationPage(req.__)); -}) - -ViewRouter.get("/login", (req, res) => { - res.setHeader("Cache-Control", "public, max-age=" + cacheTime); - res.send(GetLoginPage(req.__)) -}) - -ViewRouter.get("/admin", GetUserMiddleware(false, true), (req: Request, res, next) => { - if (!req.isAdmin) res.sendStatus(HttpStatusCode.FORBIDDEN) - else next() -}, (req, res) => { - res.send(GetAdminPage(req.__)) -}) - -// ViewRouter.get("/user", Stacker(GetUserMiddleware(false, true), (req, res) => { -// res.setHeader("Cache-Control", "public, max-age=" + cacheTime); -// res.send(GetUserPage(req.__)); -// })); - -ViewRouter.get("/auth", Stacker(GetUserMiddleware(false, true), async (req, res) => { - let { scope, redirect_uri, state, client_id }: { [key: string]: string } = req.query; - const sendError = (type) => { - res.redirect(redirect_uri += `?error=${type}&state=${state}`); - } - let client = await Client.findOne({ client_id: client_id }) - if (!client) { - return sendError("unauthorized_client") - } - - let permissions: IPermission[] = []; - let proms: PromiseLike[] = []; - if (scope) { - for (let perm of scope.split(";").filter(e => e !== "read_user")) { - proms.push(Permission.findById(perm).then(p => { - if (!p) return Promise.reject(new Error()); - permissions.push(p); - })); - } - } - let err = false; - await Promise.all(proms).catch(e => { - err = true; - }) - Logging.debug(err); - if (err) { - return sendError("invalid_scope") - } - let scopes = await Promise.all(permissions.map(async perm => { - let client = await Client.findById(perm.client); - return { - name: perm.name, - description: perm.description, - logo: client.logo - } - })) - res.send(GetAuthPage(req.__, client.name, scopes)); -})); - -if (config.core.dev) { - const logo = "data:image/png;base64,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" - ViewRouter.get("/devauth", (req, res) => { - res.send(GetAuthPage(req.__, "Test 05265", [ - { - name: "Access Profile", - description: "It allows the application to know who you are. Required for all applications. And a lot of more Text, because why not? This will not stop, till it is multiple lines long and maybe kill the layout, so keep reading as long as you like, but I promise it will get boring after some time. So this should be enougth.", - logo: logo - }, - { - name: "Test 1", - description: "This is not an real permission. This is used just to verify the layout", - logo: logo - }, - { - name: "Test 2", - description: "This is not an real permission. This is used just to verify the layout", - logo: logo - } - ])) - }) -} - +import { Router, IRouter, Request } from "express" +import GetLoginPage from "./login"; +import GetAuthPage from "./authorize"; +import promiseMiddleware from "../helper/promiseMiddleware"; +import config from "../config"; +import * as Handlebars from "handlebars"; +import GetRegistrationPage from "./register"; +import GetAdminPage from "./admin"; +import { HttpStatusCode } from "../helper/request_error"; +import * as moment from "moment"; +import Permission, { IPermission } from "../models/permissions"; +import Client from "../models/client"; +import { Logging } from "@hibas123/nodelogging"; +import Stacker from "../api/middlewares/stacker"; +import { UserMiddleware, GetUserMiddleware } from "../api/middlewares/user"; +// import GetUserPage from "./user"; + +Handlebars.registerHelper("appname", () => config.core.name); + +const cacheTime = config.core.dev ? moment.duration(1, "month").asSeconds() : 10; + +const ViewRouter: IRouter = Router(); +ViewRouter.get("/", UserMiddleware, (req, res) => { + res.send("This is the main page") +}) + +ViewRouter.get("/register", (req, res) => { + res.setHeader("Cache-Control", "public, max-age=" + cacheTime); + res.send(GetRegistrationPage(req.__)); +}) + +ViewRouter.get("/login", (req, res) => { + res.setHeader("Cache-Control", "public, max-age=" + cacheTime); + res.send(GetLoginPage(req.__)) +}) + +ViewRouter.get("/code", (req, res) => { + res.setHeader("Cache-Control", "no-cache"); + if (req.query.error) + res.send("Some error occured: " + req.query.error); + else + res.send(`Your code is: ${req.query.code}`); +}) + +ViewRouter.get("/admin", GetUserMiddleware(false, true), (req: Request, res, next) => { + if (!req.isAdmin) res.sendStatus(HttpStatusCode.FORBIDDEN) + else next() +}, (req, res) => { + res.send(GetAdminPage(req.__)) +}) + +// ViewRouter.get("/user", Stacker(GetUserMiddleware(false, true), (req, res) => { +// res.setHeader("Cache-Control", "public, max-age=" + cacheTime); +// res.send(GetUserPage(req.__)); +// })); + +ViewRouter.get("/auth", Stacker(GetUserMiddleware(false, true), async (req, res) => { + let { scope, redirect_uri, state, client_id }: { [key: string]: string } = req.query; + const sendError = (type) => { + res.redirect(redirect_uri += `?error=${type}&state=${state}`); + } + let client = await Client.findOne({ client_id: client_id }) + if (!client) { + return sendError("unauthorized_client") + } + + let permissions: IPermission[] = []; + let proms: PromiseLike[] = []; + if (scope) { + for (let perm of scope.split(";").filter(e => e !== "read_user")) { + proms.push(Permission.findById(perm).then(p => { + if (!p) return Promise.reject(new Error()); + permissions.push(p); + })); + } + } + let err = false; + await Promise.all(proms).catch(e => { + err = true; + }) + Logging.debug(err); + if (err) { + return sendError("invalid_scope") + } + let scopes = await Promise.all(permissions.map(async perm => { + let client = await Client.findById(perm.client); + return { + name: perm.name, + description: perm.description, + logo: client.logo + } + })) + res.send(GetAuthPage(req.__, client.name, scopes)); +})); + +if (config.core.dev) { + const logo = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAlwSFlzAAASdAAAEnQB3mYfeAAAAAZiS0dEAP8A/wD/oL2nkwAAAFR0RVh0Y29tbWVudABGaWxlIHNvdXJjZTogaHR0cHM6Ly9jb21tb25zLndpa2ltZWRpYS5vcmcvd2lraS9GaWxlOkdvb2dsZS1mYXZpY29uLTIwMTUucG5nLE0iZQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNS0wOS0wMlQxNzo1ODowOCswMDowMNkAVU4AAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTUtMDktMDJUMTc6NTg6MDgrMDA6MDCoXe3yAAAAR3RFWHRzb2Z0d2FyZQBJbWFnZU1hZ2ljayA2LjcuNy0xMCAyMDE0LTAzLTA2IFExNiBodHRwOi8vd3d3LmltYWdlbWFnaWNrLm9yZ2+foqIAAAAYdEVYdFRodW1iOjpEb2N1bWVudDo6UGFnZXMAMaf/uy8AAAAYdEVYdFRodW1iOjpJbWFnZTo6aGVpZ2h0ADQwMUEAWp0AAAAXdEVYdFRodW1iOjpJbWFnZTo6V2lkdGgAMzk0OUtQUwAAABl0RVh0VGh1bWI6Ok1pbWV0eXBlAGltYWdlL3BuZz+yVk4AAAAXdEVYdFRodW1iOjpNVGltZQAxNDQxMjE2Njg4mYj7RAAAABN0RVh0VGh1bWI6OlNpemUAMTcuN0tCQhK/wrgAAAAzdEVYdFRodW1iOjpVUkkAZmlsZTovLy90bXAvbG9jYWxjb3B5XzFmZGViZjk0YmZkZC0xLnBuZ8EhOmkAAAkUSURBVGhDzZkLcBXVGcf/u/f9yM07gDq06Rh5BZTAtKMVwQGqaFEZmNLWgoBO1RRFausjbR1qKR0rHUDFtwVtqWPHgc4UmBq1NASUiFQGwiskMqZMSW6Tm+Q+knvvvvp9u0uamNxXctO5P9i5u+ec3T3/c77zfd/ZCBqBMUANhaB2+Ok3CMgSYLVC9ORBLC2F6CswW2WPrAmJHa5D9EAtpGMNkC+2AvE4IIrGcRlV1Q/BRqLGXwn7zNlwzF0A54JbqVIw2oyQUQmRms4g8voLiB14H5qiQHS5AJsNsFghCIk7pr+S2kOSoMWi+r2OG+fBc99a2K+tMltlxoiESKdPIvirGvo9ATHPB9gdEAaOfIboXYjHoAaDsF59DXy/+A3s180ya9MjIyGaLKP70QdoBmohFhSRidDoJxn5jKGuaLSe1K4uMrn5KNj6GgSLxaxMTtpCYh/VoXv9/fRgK0AmlMx0Rg0LivbpA1e4fQfss683KxKTlj2EXtiMrgdWQHB76HCPrQiGni+46D30vsDq7yD00hazIjEphfTUPILIGy+S2xyX9jRnDV53Ah0SecAUJDWtnifXIVq7j9ZD4cjWApuIecroT0jzOdwt9T9+eH/8M3hX/dAsTUxCIcFtz6D3zVdgKSzOSITGsYJiiEZeCGTjPKoamwq/hutoVgXycrDbE86wIaIdeY9vgOfuNWZpcoYVEj10AN3V9xjmlO4IUqe1cAiC0wX79XNg/+Zc2KZUQiwuheBwQCPz0Do7IDWfI8dxEPFD/4AW7IFA7lugqH8ZXYSfRPx8IzzLV5qlqRkihIOT/+uTIOQXpBUb+HbukFhUDO9Dj8H17SVmTWqif38Pod9thNrepr+PUf1t8G34LdxLv6dfp8sQIYEHV0I+8U/da6SCRauBThLwE3gpKo+UMGUH4eeeJRUKfL/eCvedy8ya9BkkJHa0EV2rbqc8qCylSWlmelH89l9hLb/aLB05sSOHoHxxAe7lK8ySzBgkJL7/K+jZ5oMa9kJ0Ui6UQIu+HkhE6YdHIZKvzwX6F4EapE6JrSj6ZSMc0wNQQjb2nkNgr6R2B1C6rz5nRDD9QrTmGmh0pUWs8N3bBN/3m2kRkxiFpsUUxJOnBjpQsJkCJC3uXKLftKT95Ovt5Nc5klLPBZcCpdNJplYJNSqSC+X4EIO1YhKKfv9nviWn0GdE7dhrrAddBCNA66PNjy+Ooqc/hb0iSDHCSibVjfxNW802uYXec82/e4CRDUCmqBy1wFd9Bu7bz8M27RuwjL/CrMwtdNOS6ydSh/9FE0L7i2Eh6xNliJN3QJywyixLn4ZmGR80ynDY0ssS0oUzHq8TqF5IGzsWIr1H64Pznn7T+hK0jLSYDNuiPhJEd2bIm/VxbN4bo5dmWQiNb1zW8NmmPDIojeIF/TcWyfBo1EBwUj40AhGM1SLA5RDgzvLhoYPF6AajSQHjbckiOTs29yTzInfgLnPXuno1mhE5bBYngVXby4zzHIPFRKIsJM00nUK6eZJb0OqGQtMiwuI1RjwZrFVqN85zDN6DWmgyRMHGO0AuSaKGvJkWOWde5Bb68iVvaJiWvuNMLISbIU71csgsyQx+GX9YlBUtoyPZ2DJ6PXW/wGXGc8H7NSrUffDwUGMbie299I5ZkBkOirMFlCjnu4W0j5I8SpOop8nEsFk5rTTMov5NgCScuR9q66u0dx4a2S1QybIUPNNdiX3iPBy883mzZuyZWRNCoSexP5Jo1kq8Anav95gzUkZbyy9NCA+EFTJNhoalnbfg1eh0XAg0oqWn1Wgwxnx4ilIiHukEIhiZ+nztRONLjC5ELF5onPW7WA02QcJ5uRCV/mU4K+ejUKBM2OHDw3UbzTZjy866ONx28yIBMQm44RrjC4wuhBEn3EE6FCpQYaUE8Y3IVNzceRsJUuEWKEXhdSJacTrQgj81Udo/hjRdUnH8C0Vfl4ng9cN51vxKo1H/xkqLnIZQNw2gdGpl13zUx8ahWIwNmVpu3t7bgYPLdqHcd5VZml0WboogTvbPOVoiWMRXS0T8odr42tM/I4JnKlq812Fm22J8Gi9BsWWoCIa/rpS6irDgL6vRFukwS7PH2p19CMWSi2DCUeCem/7nnPqFMN3T96MtGiRTkvQYmQiLSJstmxc3vPtdfNJ+wiwdPeveiuJIs6JntclQKOXl9bOgMoGQWYUTsKR8Hnpl2nekwEpiCmnxL9v/MJ468pxZOjJawmdx6/ZjaDjnRL4ruQgmSN1bv2iwJ+hfIwOZ/MdFcFuc+singm8PS72wW2z40Yy7sXrKEjpP4W5MzgY+x5bjO/G31noUuDV4Ox6Eq2M5NAv1lJzMcHDEd1AQrH1y8KeoYYUc85/CXXurMc5doq+JdFBo3xmRe3VhVWXTMOeKWZhRMgnjXCVwWR2IqRK6oj16HOLnf9T2Gf4d9sNjc8PJwuk1mqUHtvBseC6yi6duiYP/LsLP9gc17HnEjYoJgwd5WCHMK43vYNPRl/WFnclfqFR6nESdjisS/crUHY36yGHVeI1VsOizZxNtlLVy1B74bGol9kFQ3PC0PgtrrJyuI7pIJhDWcO9cG9be4jAKBpBQCLOh4XnsPLMHJc7CjMQMZODj030GpYw0O2G429bBEVhM570IRVVUlYt4ec3wH9eTCmGe/mQ7Xj/1LsoynJnRolFgZlOzB2+C8vkTqBivYdfaxN8MUgphdpzejacattHMFOne6v8Fd61TuoQ5xXfgrdueMEuHJy0hzMmOJvzg/Z8iJsfhpQU61rPD66sz2oWHZqzAY7PuM0sTk7aQyzx+eDPeplwr354HB3mbbAtSKN/riYd1U35t/kZUFleYNcnJWAhzMdyGmo+34MDFBuTZPOQ+HRRzBsXWjOAu8AyE4hHk2d14tGoNVk6+y6xNjxEJuYy/txPbT+7CnpYPaBRDFERdlLFaaR1ZKWXgvcTQ2eLX8T+Ftgzc+ZgSpw2SpMeeNVOXYnH5zWbLzBiVkIGc6jyP2tbD+LjtOM51XdDNQ6POshgjjrAI45pn8CrveFSVTsGcK2fjWxNv1M10NGRNyHAEKJKzuXCA5FliJ5HvyNP3NdkF+C8dn/ikO2g+hwAAAABJRU5ErkJggg==" + ViewRouter.get("/devauth", (req, res) => { + res.send(GetAuthPage(req.__, "Test 05265", [ + { + name: "Access Profile", + description: "It allows the application to know who you are. Required for all applications. And a lot of more Text, because why not? This will not stop, till it is multiple lines long and maybe kill the layout, so keep reading as long as you like, but I promise it will get boring after some time. So this should be enougth.", + logo: logo + }, + { + name: "Test 1", + description: "This is not an real permission. This is used just to verify the layout", + logo: logo + }, + { + name: "Test 2", + description: "This is not an real permission. This is used just to verify the layout", + logo: logo + } + ])) + }) +} + export default ViewRouter; \ No newline at end of file diff --git a/views/src/authorize/authorize.js b/views/src/authorize/authorize.js index 8c6ccb2..248682c 100644 --- a/views/src/authorize/authorize.js +++ b/views/src/authorize/authorize.js @@ -7,9 +7,12 @@ function submit() { document.getElementById("cancel").onclick = () => { let u = new URL(window.location); let uri = u.searchParams.get("redirect_uri"); + if (uri === "$local") { + uri = "/code"; + } window.location.href = uri + "?error=access_denied&state=" + u.searchParams.get("state"); } document.getElementById("allow").onclick = () => { submit() -} +} \ No newline at end of file