import cookie from "cookie"; import * as jwt from "jsonwebtoken"; import { Action } from "routing-controllers"; import { getConnectionManager } from 'typeorm'; import { config } from './config'; import { IllegalJWTError, NoPermissionError, UserNonexistantOrRefreshtokenInvalidError } from './errors/AuthError'; import { JwtCreator, JwtUser } from './JwtCreator'; import { User } from './models/entities/User'; /** * Handels authorisation verification via jwt's for all api endpoints using the @Authorized decorator. * @param action Routing-Controllers action object that provides request and response objects among other stuff. * @param permissions The permissions that the endpoint using @Authorized requires. */ const authchecker = async (action: Action, permissions: string[] | string) => { let required_permissions = undefined; if (typeof permissions === "string") { required_permissions = [permissions] } else { required_permissions = permissions } 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"] }, { relations: ['permissions'] }) if (!user) { throw new UserNonexistantOrRefreshtokenInvalidError() } if (!jwtPayload["permissions"]) { throw new NoPermissionError(); } action.response.local = {} action.response.local.jwtPayload = jwtPayload; for (let required_permission of required_permissions) { if (!(jwtPayload["permissions"].includes(required_permission))) { return false; } } return true; } /** * Handels 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() } let newAccess = JwtCreator.createAccess(user); action.response.header("authorization", "Bearer " + newAccess); return await new JwtUser(user); } export default authchecker