This commit is contained in:
Fabian Stamm 2019-12-16 14:05:54 +01:00
commit 327a38db4b
4 changed files with 146 additions and 115 deletions

View File

@ -12,6 +12,8 @@ import { ObjectID } from "bson";
const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Response) => { const AuthRoute = Stacker(GetUserMiddleware(true), async (req: Request, res: Response) => {
let { response_type, client_id, redirect_uri, scope, state, nored } = req.query; let { response_type, client_id, redirect_uri, scope, state, nored } = req.query;
const sendError = (type) => { const sendError = (type) => {
if (redirect_uri === "$local")
redirect_uri = "/code";
res.redirect(redirect_uri += `?error=${type}&state=${state}`); 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); 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") { if (nored === "true") {
res.json({ res.json({
redirect_uri: ruri redirect_uri: ruri

View File

@ -13,12 +13,24 @@ import { JWTExpDur } from "../../keys";
import RefreshToken from "../../models/refresh_token"; import RefreshToken from "../../models/refresh_token";
import { getEncryptionKey } from "../../helper/user_key"; 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) => { const RefreshTokenRoute = Stacker(GetClientAuthMiddleware(false, false, true), async (req: Request, res: Response) => {
let grant_type = req.query.grant_type || req.body.grant_type; let grant_type = req.query.grant_type || req.body.grant_type;
if (!grant_type || grant_type === "authorization_code") { if (!grant_type || grant_type === "authorization_code") {
let code = req.query.code || req.body.code; let code = req.query.code || req.body.code;
let c = await ClientCode.findOne({ code: 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); throw new RequestError(req.__("Invalid code"), HttpStatusCode.BAD_REQUEST);
} }
@ -33,7 +45,7 @@ const RefreshTokenRoute = Stacker(GetClientAuthMiddleware(false, false, true), a
permissions: c.permissions, permissions: c.permissions,
token: randomBytes(16).toString("hex"), token: randomBytes(16).toString("hex"),
valid: true, valid: true,
validTill: moment().add(6, "months").toDate() validTill: moment().add(refreshTokenValidTime).toDate()
}); });
await RefreshToken.save(token); await RefreshToken.save(token);
await ClientCode.delete(c); 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); if (!refresh_token) throw new RequestError(req.__("refresh_token not set"), HttpStatusCode.BAD_REQUEST);
let token = await RefreshToken.findOne({ token: refresh_token }); 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 user = await User.findById(token.user);
let client = await Client.findById(token.client) let client = await Client.findById(token.client)

View File

@ -1,111 +1,119 @@
import { Router, IRouter, Request } from "express" import { Router, IRouter, Request } from "express"
import GetLoginPage from "./login"; import GetLoginPage from "./login";
import GetAuthPage from "./authorize"; import GetAuthPage from "./authorize";
import promiseMiddleware from "../helper/promiseMiddleware"; import promiseMiddleware from "../helper/promiseMiddleware";
import config from "../config"; import config from "../config";
import * as Handlebars from "handlebars"; import * as Handlebars from "handlebars";
import GetRegistrationPage from "./register"; import GetRegistrationPage from "./register";
import GetAdminPage from "./admin"; import GetAdminPage from "./admin";
import { HttpStatusCode } from "../helper/request_error"; import { HttpStatusCode } from "../helper/request_error";
import * as moment from "moment"; import * as moment from "moment";
import Permission, { IPermission } from "../models/permissions"; import Permission, { IPermission } from "../models/permissions";
import Client from "../models/client"; import Client from "../models/client";
import { Logging } from "@hibas123/nodelogging"; import { Logging } from "@hibas123/nodelogging";
import Stacker from "../api/middlewares/stacker"; import Stacker from "../api/middlewares/stacker";
import { UserMiddleware, GetUserMiddleware } from "../api/middlewares/user"; import { UserMiddleware, GetUserMiddleware } from "../api/middlewares/user";
// import GetUserPage from "./user"; // import GetUserPage from "./user";
Handlebars.registerHelper("appname", () => config.core.name); Handlebars.registerHelper("appname", () => config.core.name);
const cacheTime = config.core.dev ? moment.duration(1, "month").asSeconds() : 10; const cacheTime = config.core.dev ? moment.duration(1, "month").asSeconds() : 10;
const ViewRouter: IRouter<void> = Router(); const ViewRouter: IRouter<void> = Router();
ViewRouter.get("/", UserMiddleware, (req, res) => { ViewRouter.get("/", UserMiddleware, (req, res) => {
res.send("This is the main page") res.send("This is the main page")
}) })
ViewRouter.get("/register", (req, res) => { ViewRouter.get("/register", (req, res) => {
res.setHeader("Cache-Control", "public, max-age=" + cacheTime); res.setHeader("Cache-Control", "public, max-age=" + cacheTime);
res.send(GetRegistrationPage(req.__)); res.send(GetRegistrationPage(req.__));
}) })
ViewRouter.get("/login", (req, res) => { ViewRouter.get("/login", (req, res) => {
res.setHeader("Cache-Control", "public, max-age=" + cacheTime); res.setHeader("Cache-Control", "public, max-age=" + cacheTime);
res.send(GetLoginPage(req.__)) res.send(GetLoginPage(req.__))
}) })
ViewRouter.get("/admin", GetUserMiddleware(false, true), (req: Request, res, next) => { ViewRouter.get("/code", (req, res) => {
if (!req.isAdmin) res.sendStatus(HttpStatusCode.FORBIDDEN) res.setHeader("Cache-Control", "no-cache");
else next() if (req.query.error)
}, (req, res) => { res.send("Some error occured: " + req.query.error);
res.send(GetAdminPage(req.__)) else
}) res.send(`Your code is: ${req.query.code}`);
})
// ViewRouter.get("/user", Stacker(GetUserMiddleware(false, true), (req, res) => {
// res.setHeader("Cache-Control", "public, max-age=" + cacheTime); ViewRouter.get("/admin", GetUserMiddleware(false, true), (req: Request, res, next) => {
// res.send(GetUserPage(req.__)); if (!req.isAdmin) res.sendStatus(HttpStatusCode.FORBIDDEN)
// })); else next()
}, (req, res) => {
ViewRouter.get("/auth", Stacker(GetUserMiddleware(false, true), async (req, res) => { res.send(GetAdminPage(req.__))
let { scope, redirect_uri, state, client_id }: { [key: string]: string } = req.query; })
const sendError = (type) => {
res.redirect(redirect_uri += `?error=${type}&state=${state}`); // ViewRouter.get("/user", Stacker(GetUserMiddleware(false, true), (req, res) => {
} // res.setHeader("Cache-Control", "public, max-age=" + cacheTime);
let client = await Client.findOne({ client_id: client_id }) // res.send(GetUserPage(req.__));
if (!client) { // }));
return sendError("unauthorized_client")
} ViewRouter.get("/auth", Stacker(GetUserMiddleware(false, true), async (req, res) => {
let { scope, redirect_uri, state, client_id }: { [key: string]: string } = req.query;
let permissions: IPermission[] = []; const sendError = (type) => {
let proms: PromiseLike<void>[] = []; res.redirect(redirect_uri += `?error=${type}&state=${state}`);
if (scope) { }
for (let perm of scope.split(";").filter(e => e !== "read_user")) { let client = await Client.findOne({ client_id: client_id })
proms.push(Permission.findById(perm).then(p => { if (!client) {
if (!p) return Promise.reject(new Error()); return sendError("unauthorized_client")
permissions.push(p); }
}));
} let permissions: IPermission[] = [];
} let proms: PromiseLike<void>[] = [];
let err = false; if (scope) {
await Promise.all(proms).catch(e => { for (let perm of scope.split(";").filter(e => e !== "read_user")) {
err = true; proms.push(Permission.findById(perm).then(p => {
}) if (!p) return Promise.reject(new Error());
Logging.debug(err); permissions.push(p);
if (err) { }));
return sendError("invalid_scope") }
} }
let scopes = await Promise.all(permissions.map(async perm => { let err = false;
let client = await Client.findById(perm.client); await Promise.all(proms).catch(e => {
return { err = true;
name: perm.name, })
description: perm.description, Logging.debug(err);
logo: client.logo if (err) {
} return sendError("invalid_scope")
})) }
res.send(GetAuthPage(req.__, client.name, scopes)); let scopes = await Promise.all(permissions.map(async perm => {
})); let client = await Client.findById(perm.client);
return {
if (config.core.dev) { name: perm.name,
const logo = "data:image/png;base64,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" description: perm.description,
ViewRouter.get("/devauth", (req, res) => { logo: client.logo
res.send(GetAuthPage(req.__, "Test 05265", [ }
{ }))
name: "Access Profile", res.send(GetAuthPage(req.__, client.name, scopes));
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
}, if (config.core.dev) {
{ const logo = "data:image/png;base64,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"
name: "Test 1", ViewRouter.get("/devauth", (req, res) => {
description: "This is not an real permission. This is used just to verify the layout", res.send(GetAuthPage(req.__, "Test 05265", [
logo: logo {
}, 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.",
name: "Test 2", logo: logo
description: "This is not an real permission. This is used just to verify the layout", },
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; export default ViewRouter;

View File

@ -7,9 +7,12 @@ function submit() {
document.getElementById("cancel").onclick = () => { document.getElementById("cancel").onclick = () => {
let u = new URL(window.location); let u = new URL(window.location);
let uri = u.searchParams.get("redirect_uri"); let uri = u.searchParams.get("redirect_uri");
if (uri === "$local") {
uri = "/code";
}
window.location.href = uri + "?error=access_denied&state=" + u.searchParams.get("state"); window.location.href = uri + "?error=access_denied&state=" + u.searchParams.get("state");
} }
document.getElementById("allow").onclick = () => { document.getElementById("allow").onclick = () => {
submit() submit()
} }