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) => {
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

View File

@ -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)

View File

@ -34,6 +34,14 @@ ViewRouter.get("/login", (req, res) => {
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()

View File

@ -7,6 +7,9 @@ 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");
}