From f1db8836092269966a7f54e69b1f20c171e81b21 Mon Sep 17 00:00:00 2001 From: Nicolai Ort Date: Fri, 15 Jan 2021 22:16:28 +0100 Subject: [PATCH] Implemented a baisc user checker/getter ref #100 --- src/app.ts | 2 ++ src/middlewares/UserChecker.ts | 49 ++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/src/app.ts b/src/app.ts index 44060da..6e814b3 100644 --- a/src/app.ts +++ b/src/app.ts @@ -5,10 +5,12 @@ import { config, e as errors } from './config'; import loaders from "./loaders/index"; import authchecker from "./middlewares/authchecker"; import { ErrorHandler } from './middlewares/ErrorHandler'; +import UserChecker from './middlewares/UserChecker'; const CONTROLLERS_FILE_EXTENSION = process.env.NODE_ENV === 'production' ? 'js' : 'ts'; const app = createExpressServer({ authorizationChecker: authchecker, + currentUserChecker: UserChecker, middlewares: [ErrorHandler], development: config.development, cors: true, diff --git a/src/middlewares/UserChecker.ts b/src/middlewares/UserChecker.ts index 93408ef..603fe6e 100644 --- a/src/middlewares/UserChecker.ts +++ b/src/middlewares/UserChecker.ts @@ -1,9 +1,58 @@ +import cookie from "cookie"; +import * as jwt from "jsonwebtoken"; import { Action } from 'routing-controllers'; +import { getConnectionManager } from 'typeorm'; +import { config } from '../config'; +import { IllegalJWTError, UserDisabledError, UserNonexistantOrRefreshtokenInvalidError } from '../errors/AuthError'; +import { JwtCreator, JwtUser } from '../jwtcreator'; +import { User } from '../models/entities/User'; /** * TODO: */ const UserChecker = async (action: Action) => { + let jwtPayload = undefined + try { + let provided_token = "" + action.request.headers["authorization"].replace("Bearer ", ""); + jwtPayload = jwt.verify(provided_token, config.jwt_secret); + jwtPayload = jwtPayload["userdetails"]; + } catch (error) { + jwtPayload = await refresh(action); + } + const user = await getConnectionManager().get().getRepository(User).findOne({ id: jwtPayload["id"], refreshTokenCount: jwtPayload["refreshTokenCount"] }) + if (!user) { throw new UserNonexistantOrRefreshtokenInvalidError() } + if (user.enabled == false) { throw new UserDisabledError(); } + return user; }; + +/** + * Handles soft-refreshing of access-tokens. + * @param action Routing-Controllers action object that provides request and response objects among other stuff. + */ +const refresh = async (action: Action) => { + let refresh_token = undefined; + try { + refresh_token = cookie.parse(action.request.headers["cookie"])["lfk_backend__refresh_token"]; + } + catch { + throw new IllegalJWTError(); + } + + let jwtPayload = undefined; + try { + jwtPayload = jwt.verify(refresh_token, config.jwt_secret); + } catch (error) { + throw new IllegalJWTError(); + } + + const user = await getConnectionManager().get().getRepository(User).findOne({ id: jwtPayload["id"], refreshTokenCount: jwtPayload["refreshTokenCount"] }, { relations: ['permissions', 'groups', 'groups.permissions'] }) + if (!user) { throw new UserNonexistantOrRefreshtokenInvalidError() } + if (user.enabled == false) { throw new UserDisabledError(); } + + let newAccess = JwtCreator.createAccess(user); + action.response.header("authorization", "Bearer " + newAccess); + + return await new JwtUser(user); +} export default UserChecker; \ No newline at end of file