diff --git a/src/modules/auth/controllers/tokenValidation.controller.ts b/src/modules/auth/controllers/tokenValidation.controller.ts index 7e19545..49f641e 100644 --- a/src/modules/auth/controllers/tokenValidation.controller.ts +++ b/src/modules/auth/controllers/tokenValidation.controller.ts @@ -4,10 +4,10 @@ import { returnReadResponse } from "../../../helpers/callback/httpResponse"; import { mainErrorHandler } from "../../../helpers/error/handler"; import { parse } from "cookie"; -export const tokenValidationController = (ctx: Context) => { +export const tokenValidationController = async (ctx: Context) => { try { const { auth_token } = parse(ctx.request.headers.get("cookie") || ""); - const validationResult = tokenValidationService(auth_token as string); + const validationResult = await tokenValidationService(auth_token as string); return returnReadResponse( ctx.set, 200, diff --git a/src/modules/auth/services/http/tokenValidation.service.ts b/src/modules/auth/services/http/tokenValidation.service.ts index 6bf5b4a..aa9b28d 100644 --- a/src/modules/auth/services/http/tokenValidation.service.ts +++ b/src/modules/auth/services/http/tokenValidation.service.ts @@ -1,12 +1,34 @@ import { AppError } from "../../../../helpers/error/instances/app"; import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder"; import { jwtDecode } from "../../../../helpers/http/jwt/decode"; +import { redis } from "../../../../utils/databases/redis/connection"; +import { checkUserSessionInDBService } from "../../../userSession/services/internal/checkUserSessionInDB.service"; -export const tokenValidationService = (payload: string) => { +export const tokenValidationService = async (payload: string) => { try { if (!payload || payload.trim() === "") throw new AppError(401, "Unauthorized: No token provided"); const decoded = jwtDecode(payload); + + const redisValidationResult = await redis.hgetall( + `${process.env.APP_NAME}:users:${decoded.user.id}:sessions:${decoded.id}`, + ); + if ( + !redisValidationResult || + Object.keys(redisValidationResult).length === 0 + ) { + const dbValidationResult = await checkUserSessionInDBService(decoded.id); + if (!dbValidationResult) + throw new AppError(403, "Unauthorized: Invalid session"); + const createRedisKey = `${process.env.APP_NAME}:users:${decoded.user.id}:sessions:${decoded.id}`; + await redis.hset(createRedisKey, { + userId: decoded.user.id, + sessionId: decoded.id, + validUntil: decoded.validUntil, + }); + await redis.expire(createRedisKey, Number(process.env.SESSION_EXPIRE)); + } + return decoded; } catch (error) { ErrorForwarder(error); diff --git a/src/modules/userSession/repositories/checkUserSession.repository.ts b/src/modules/userSession/repositories/checkUserSession.repository.ts new file mode 100644 index 0000000..9a8bb31 --- /dev/null +++ b/src/modules/userSession/repositories/checkUserSession.repository.ts @@ -0,0 +1,16 @@ +import { AppError } from "../../../helpers/error/instances/app"; +import { userSessionModel } from "../userSession.model"; + +export const checkUserSessionRepository = async (sessionId: string) => { + try { + return await userSessionModel.findUnique({ + where: { + id: sessionId, + isAuthenticated: true, + deletedAt: null, + }, + }); + } catch (error) { + throw new AppError(500, "Database error during session validation", error); + } +}; diff --git a/src/modules/userSession/services/internal/checkUserSessionInDB.service.ts b/src/modules/userSession/services/internal/checkUserSessionInDB.service.ts new file mode 100644 index 0000000..85ab0e3 --- /dev/null +++ b/src/modules/userSession/services/internal/checkUserSessionInDB.service.ts @@ -0,0 +1,13 @@ +import { ErrorForwarder } from "../../../../helpers/error/instances/forwarder"; +import { checkUserSessionRepository } from "../../repositories/checkUserSession.repository"; + +export const checkUserSessionInDBService = async ( + sessionId: string, +): Promise => { + try { + const dbValidationResult = await checkUserSessionRepository(sessionId); + return dbValidationResult ? true : false; + } catch (error) { + ErrorForwarder(error); + } +};