From 4451e81fe111be1604882d8c122674b0031ccc3e Mon Sep 17 00:00:00 2001 From: Czekaj Tom Date: Sat, 6 Jan 2024 05:06:02 +0100 Subject: [PATCH 1/4] :rocket: Change error message when at/rt payload is invalid or missing --- src/auth/guards/at.guard.ts | 2 +- src/auth/guards/rt.guard.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/auth/guards/at.guard.ts b/src/auth/guards/at.guard.ts index 1641121..14041aa 100644 --- a/src/auth/guards/at.guard.ts +++ b/src/auth/guards/at.guard.ts @@ -29,7 +29,7 @@ export class AtGuard implements CanActivate{ throw new UnauthorizedException("Invalid access token"); } if(!payload) - throw new UnauthorizedException("Invalid access token"); + throw new UnauthorizedException("Invalid or missing access token payload"); if(payload.type !== TokenType.ACCESS) throw new UnauthorizedException("Invalid access type: " + payload.type); if(await this.tokensService.isTokenBlacklisted(token, false)) diff --git a/src/auth/guards/rt.guard.ts b/src/auth/guards/rt.guard.ts index 3535628..34e9d89 100644 --- a/src/auth/guards/rt.guard.ts +++ b/src/auth/guards/rt.guard.ts @@ -32,7 +32,7 @@ export class RtGuard implements CanActivate{ throw new UnauthorizedException("Invalid refresh token"); } if(!payload) - throw new UnauthorizedException("Invalid refresh token"); + throw new UnauthorizedException("Invalid or missing refresh token payload"); if(payload.type !== TokenType.REFRESH) throw new UnauthorizedException("Invalid refresh type: " + payload.type); if(await this.tokensService.isTokenBlacklisted(token, true)){ From 47e6c3fbe0f325a9eed6215efc8d4a81df706b92 Mon Sep 17 00:00:00 2001 From: Czekaj Tom Date: Sat, 6 Jan 2024 05:57:30 +0100 Subject: [PATCH 2/4] :loud_sound: Improve middleware (but not fixed) --- src/app.module.ts | 9 +++++++-- src/app.ts | 8 +++++--- src/middlewares/logger.middleware.ts | 21 ++++++++------------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/app.module.ts b/src/app.module.ts index 7c4b44e..1452619 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -1,4 +1,4 @@ -import {Module} from "@nestjs/common"; +import {MiddlewareConsumer, Module} from "@nestjs/common"; import {AuthModule} from "./auth/auth.module"; import {VersionModule} from "./version/version.module"; import {ConfigModule} from "@nestjs/config"; @@ -12,6 +12,7 @@ import {ScheduleModule} from "@nestjs/schedule"; import {TasksModule} from "./tasks/tasks.module"; import {SecretsModule} from "./secrets/secrets.module"; import {AccountsModule} from "./accounts/accounts.module"; +import {LoggerMiddleware} from "./middlewares/logger.middleware"; @Module({ imports: [ @@ -30,4 +31,8 @@ import {AccountsModule} from "./accounts/accounts.module"; AccountsModule, ], }) -export class AppModule{} +export class AppModule{ + configure(consumer: MiddlewareConsumer){ + consumer.apply(LoggerMiddleware).forRoutes("*"); + } +} diff --git a/src/app.ts b/src/app.ts index ee0658d..54f0a54 100644 --- a/src/app.ts +++ b/src/app.ts @@ -12,9 +12,12 @@ import * as dotenv from "dotenv"; import * as fs from "fs"; import * as os from "os"; import {SwaggerTheme} from "swagger-themes"; +import {Logger} from "@nestjs/common"; dotenv.config(); +const logger: Logger = new Logger("Main"); + async function bootstrap(){ switch (process.env.SERVER_TYPE){ case "http": @@ -28,7 +31,7 @@ async function bootstrap(){ await startHttpsServer(); break; default: - console.error("Invalid SERVER_TYPE"); + logger.error("Invalid SERVER_TYPE"); process.exit(1); } } @@ -53,7 +56,7 @@ function getServerAddress(bindAddress: string, port: string | number, protocol: } function logServerStart(bindAddress: string, port: string | number, protocol: string){ - console.log(`Server started on ${getServerAddress(bindAddress, port, protocol)}`); + logger.log(`Server started on ${getServerAddress(bindAddress, port, protocol)}`); } async function startHttpServer(){ @@ -83,7 +86,6 @@ async function loadServer(server: NestFastifyApplication, serv }); // Middlewares - server.use(new LoggerMiddleware().use); // await server.register(helmet, { // contentSecurityPolicy: false, // }); diff --git a/src/middlewares/logger.middleware.ts b/src/middlewares/logger.middleware.ts index 8e48732..3df2f92 100644 --- a/src/middlewares/logger.middleware.ts +++ b/src/middlewares/logger.middleware.ts @@ -1,28 +1,23 @@ -import {Injectable, NestMiddleware} from "@nestjs/common"; +import {Injectable, Logger, NestMiddleware} from "@nestjs/common"; import {FastifyReply, FastifyRequest} from "fastify"; @Injectable() export class LoggerMiddleware implements NestMiddleware{ - private static getCurrentTime(): string{ - const now = new Date(); - const hours = String(now.getHours()).padStart(2, "0"); - const minutes = String(now.getMinutes()).padStart(2, "0"); - const seconds = String(now.getSeconds()).padStart(2, "0"); - return `[${hours}:${minutes}:${seconds}]`; - } + + static logger: Logger = new Logger(LoggerMiddleware.name); use(req: FastifyRequest["raw"], res: FastifyReply["raw"], next: () => void){ const startTime = Date.now(); - res.on("finish", () => { - const currentTime = LoggerMiddleware.getCurrentTime(); + res.end = () => { const httpOrHttps = req.connection.localPort.toString() === process.env.HTTPS_PORT ? "HTTPS" : "HTTP"; const method = req.method; const path = req.url; const statusCode = res.statusCode; const duration = Date.now() - startTime; - const resSize = res.getHeader("Content-Length") || "N/A"; - console.log(`${currentTime} ${httpOrHttps} ${method} ${path} ${statusCode} ${duration}ms ${resSize}`); - }); + const resSize = res.getHeader("content-length") || "N/A"; + LoggerMiddleware.logger.log(`${httpOrHttps} ${method} ${path} ${statusCode} ${duration}ms ${resSize}`); + return null; + }; next(); } } From 13616bdf5252dbdffcd83e7c49939366db16cbb2 Mon Sep 17 00:00:00 2001 From: Czekaj Tom Date: Sat, 6 Jan 2024 06:01:59 +0100 Subject: [PATCH 3/4] :bug: Change error status when token is not in database --- src/auth/guards/at.guard.ts | 3 +++ src/auth/guards/rt.guard.ts | 3 +++ src/services/tokens.service.ts | 9 ++++++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/auth/guards/at.guard.ts b/src/auth/guards/at.guard.ts index 14041aa..3dc1fea 100644 --- a/src/auth/guards/at.guard.ts +++ b/src/auth/guards/at.guard.ts @@ -22,6 +22,9 @@ export class AtGuard implements CanActivate{ const token = AuthController.extractTokenFromHeader(request); if(!token) throw new UnauthorizedException("Missing access token"); + const dbToken = await this.tokensService.getTokenEntity(token, false, false); + if(!dbToken) + throw new UnauthorizedException("Token not found in database"); let payload: AtPayloadModel; try{ payload = this.jwtService.verifyJWT(token, this.configService.get("AT_KEY")); diff --git a/src/auth/guards/rt.guard.ts b/src/auth/guards/rt.guard.ts index 34e9d89..0d6630b 100644 --- a/src/auth/guards/rt.guard.ts +++ b/src/auth/guards/rt.guard.ts @@ -25,6 +25,9 @@ export class RtGuard implements CanActivate{ const token = AuthController.extractTokenFromHeader(request); if(!token) throw new UnauthorizedException("Missing refresh token"); + const dbToken = await this.tokensService.getTokenEntity(token, true, false); + if(!dbToken) + throw new UnauthorizedException("Token not found in database"); let payload: AtPayloadModel; try{ payload = this.jwtService.verifyJWT(token, this.configService.get("RT_KEY")); diff --git a/src/services/tokens.service.ts b/src/services/tokens.service.ts index d9720e9..231af6e 100644 --- a/src/services/tokens.service.ts +++ b/src/services/tokens.service.ts @@ -54,7 +54,7 @@ export class TokensService{ return this.jwtService.generateJWT({...payload}, this.configService.get("VC_DURATION") + "m", this.configService.get("CT_KEY")); } - async getTokenEntity(token: string, isRefresh: boolean): Promise{ + async getTokenEntity(token: string, isRefresh: boolean, exception: boolean = true): Promise{ const sum = this.encryptionService.getSum(token).substring(0, 10); const tokens = await this.prismaService.tokens.findMany({ where: { @@ -62,12 +62,15 @@ export class TokensService{ is_refresh: isRefresh, }, }); - if(!tokens) + if(!tokens && exception) throw new NotFoundException("Token not found"); for(const dbToken of tokens) if(await this.encryptionService.compareHash(dbToken.token, token)) return dbToken; - throw new NotFoundException("Token not found"); + if(exception) + throw new NotFoundException("Token not found"); + else + return null; } async blacklistToken(token: string, isRefresh: boolean){ From 1bd330de502bcb68af523653a46f21a5e84db2f7 Mon Sep 17 00:00:00 2001 From: Czekaj Tom Date: Sat, 6 Jan 2024 06:03:14 +0100 Subject: [PATCH 4/4] :rotating_light: Fix linter errors --- src/app.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app.ts b/src/app.ts index 54f0a54..c24414f 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,7 +1,6 @@ import {FastifyAdapter, NestFastifyApplication} from "@nestjs/platform-fastify"; import {CustomValidationPipe} from "./pipes/custom-validation.pipe"; import {DocumentBuilder, SwaggerModule} from "@nestjs/swagger"; -import {LoggerMiddleware} from "./middlewares/logger.middleware"; // import compression from "@fastify/compress"; // import helmet from "@fastify/helmet"; import {RawServerDefault} from "fastify";