From 76e19ca28dc183f698049080b62e88f9feddf036 Mon Sep 17 00:00:00 2001 From: Philipp Dormann Date: Sat, 5 Dec 2020 17:59:43 +0100 Subject: [PATCH] implement proper jwt checking in authchecker ref #12 --- src/app.ts | 3 +-- src/authchecker.ts | 13 ++++++++++--- src/errors/AuthError.ts | 11 +++++++++++ src/middlewares/jwtauth.ts | 24 ------------------------ 4 files changed, 22 insertions(+), 29 deletions(-) delete mode 100644 src/middlewares/jwtauth.ts diff --git a/src/app.ts b/src/app.ts index e54f0ac..e19d313 100644 --- a/src/app.ts +++ b/src/app.ts @@ -5,14 +5,13 @@ import { createExpressServer } from "routing-controllers"; import authchecker from "./authchecker"; import loaders from "./loaders/index"; import { ErrorHandler } from './middlewares/ErrorHandler'; -import { JWTAuth } from './middlewares/JWTAuth'; dotenvSafe.config(); const PORT = process.env.APP_PORT || 4010; const app = createExpressServer({ authorizationChecker: authchecker, - middlewares: [ErrorHandler, JWTAuth], + middlewares: [ErrorHandler], development: process.env.NODE_ENV === "production", cors: true, routePrefix: "/api", diff --git a/src/authchecker.ts b/src/authchecker.ts index f32ec75..4264130 100644 --- a/src/authchecker.ts +++ b/src/authchecker.ts @@ -1,13 +1,15 @@ import * as jwt from "jsonwebtoken"; import { Action } from "routing-controllers"; -import { IllegalJWTError, NoPermissionError } from './errors/AuthError'; +import { getConnectionManager } from 'typeorm'; +import { IllegalJWTError, NoPermissionError, UserNonexistantOrRefreshtokenInvalidError } from './errors/AuthError'; +import { User } from './models/entities/User'; // ----------- const sampletoken = jwt.sign({ "permissions": { "TRACKS": ["read", "update", "delete", "add"] // "TRACKS": [] } -}, process.env.JWT_SECRET || "secretjwtsecret") +}, "securekey") console.log(`sampletoken: ${sampletoken}`); // ----------- const authchecker = async (action: Action, permissions: string | string[]) => { @@ -21,10 +23,15 @@ const authchecker = async (action: Action, permissions: string | string[]) => { const provided_token = action.request.query["auth"]; let jwtPayload = undefined try { - jwtPayload = jwt.verify(provided_token, process.env.JWT_SECRET || "secretjwtsecret"); + jwtPayload = jwt.verify(provided_token, "securekey"); } catch (error) { + console.log(error); throw new IllegalJWTError() } + const count = await getConnectionManager().get().getRepository(User).count({ id: jwtPayload["userdetails"]["id"], refreshTokenCount: jwtPayload["userdetails"]["refreshTokenCount"] }) + if (count !== 1) { + throw new UserNonexistantOrRefreshtokenInvalidError() + } if (jwtPayload.permissions) { action.response.local = {} action.response.local.jwtPayload = jwtPayload.permissions diff --git a/src/errors/AuthError.ts b/src/errors/AuthError.ts index a03ff24..2c2ce5b 100644 --- a/src/errors/AuthError.ts +++ b/src/errors/AuthError.ts @@ -23,6 +23,17 @@ export class IllegalJWTError extends UnauthorizedError { message = "your provided jwt could not be parsed" } +/** + * Error to throw when user is nonexistant or refreshtoken is invalid + */ +export class UserNonexistantOrRefreshtokenInvalidError extends UnauthorizedError { + @IsString() + name = "UserNonexistantOrRefreshtokenInvalidError" + + @IsString() + message = "user is nonexistant or refreshtoken is invalid" +} + /** * Error to throw when provided credentials are invalid */ diff --git a/src/middlewares/jwtauth.ts b/src/middlewares/jwtauth.ts deleted file mode 100644 index f83e0cf..0000000 --- a/src/middlewares/jwtauth.ts +++ /dev/null @@ -1,24 +0,0 @@ -import * as jwt from "jsonwebtoken"; -import { - ExpressMiddlewareInterface -} from "routing-controllers"; - -export class JWTAuth implements ExpressMiddlewareInterface { - use(request: any, response: any, next?: (err?: any) => any): any { - const token = request.headers["auth"]; - try { - /** - TODO: idk if we should always check the db if refreshtokencount is valid? - seems like a lot of db overhead - at the same time it's basically our only option to support proper logouts - */ - const jwtPayload = jwt.verify(token, "secretjwtsecret"); - // const jwtPayload = jwt.verify(token, process.env.JWT_SECRET); - response.locals.jwtPayload = jwtPayload; - } catch (error) { - console.log(error); - return response.status(401).send(); - } - next(); - } -}