From 9308a2b45df35c37149f326d73e8d2b686e2aaf7 Mon Sep 17 00:00:00 2001 From: rharkor Date: Mon, 27 May 2024 20:59:08 +0200 Subject: [PATCH] refactor: move session still exist check --- apps/app/src/components/auth/require-auth.tsx | 47 +++++++++++++++++++ apps/app/src/lib/auth/index.ts | 43 ----------------- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/apps/app/src/components/auth/require-auth.tsx b/apps/app/src/components/auth/require-auth.tsx index 41bb5add..3b8e39e9 100644 --- a/apps/app/src/components/auth/require-auth.tsx +++ b/apps/app/src/components/auth/require-auth.tsx @@ -2,9 +2,12 @@ import { headers } from "next/headers" import { redirect } from "next/navigation" import { NextResponse } from "next/server" import { getServerSession } from "next-auth" +import { z } from "zod" +import { sessionsSchema } from "@/api/me/schemas" import { authRoutes } from "@/constants/auth" import { nextAuthOptions } from "@/lib/auth" +import { redis } from "@/lib/redis" import { logger } from "@next-boilerplate/lib" export default async function requireAuth(callbackUrl?: string) { @@ -34,5 +37,49 @@ export async function getAuthApi() { return { session: null, error: NextResponse.json({ error: "Unauthorized" }, { status: 401 }) } } + //* Verify that the session still exists + if (session.user?.uuid) { + const id = session.user.id + const uuid = session.user.uuid + const getRedisSession = async () => { + const key = `session:${id}:${uuid}` + const loginSession = await redis.get(key) + if (!loginSession) { + logger.debug("Session not found", uuid) + return true + } + + //* Save last used at + //? Only if lastUsedAt is older than 1 minute (avoid spamming the redis server) + const data = JSON.parse(loginSession) as z.infer> + if (data.lastUsedAt) { + const lastUsedAt = new Date(data.lastUsedAt) + const now = new Date() + const diff = now.getTime() - lastUsedAt.getTime() + if (diff > 1000 * 60) { + return + } + } + //? Update session lastUsed + const remainingTtl = await redis.ttl(key) + //! Do not await to make the requests faster + redis.setex( + key, + remainingTtl, + JSON.stringify({ + ...(JSON.parse(loginSession) as object), + lastUsedAt: new Date(), + }) + ) + return + } + const res = await getRedisSession() + + // If res is true it means that the session is not found + if (res === true) { + return { session: null, error: NextResponse.json({ error: "Unauthorized" }, { status: 401 }) } + } + } + return { session, error: null } } diff --git a/apps/app/src/lib/auth/index.ts b/apps/app/src/lib/auth/index.ts index 7bfea8bd..5668b8c4 100644 --- a/apps/app/src/lib/auth/index.ts +++ b/apps/app/src/lib/auth/index.ts @@ -194,49 +194,6 @@ export const nextAuthOptions: NextAuthOptions = { // logger.debug("User not found", token.id) return {} as Session } - //* Verify that the session still exists - if (dbUser.hasPassword && (!token.uuid || typeof token.uuid !== "string")) { - logger.debug("Missing token uuid") - return {} as Session - } - if (token.uuid) { - const getRedisSession = async () => { - const key = `session:${dbUser.id}:${token.uuid}` - const loginSession = await redis.get(key) - if (!loginSession) { - logger.debug("Session not found", token.uuid) - return {} as Session - } - - //? Only if lastUsedAt is older than 1 minute (avoid spamming the redis server) - const data = JSON.parse(loginSession) as z.infer> - if (data.lastUsedAt) { - const lastUsedAt = new Date(data.lastUsedAt) - const now = new Date() - const diff = now.getTime() - lastUsedAt.getTime() - if (diff > 1000 * 60) { - return - } - } - //? Update session lastUsed - const remainingTtl = await redis.ttl(key) - //! Do not await to make the requests faster - redis.setex( - key, - remainingTtl, - JSON.stringify({ - ...(JSON.parse(loginSession) as object), - lastUsedAt: new Date(), - }) - ) - return - } - const res = await getRedisSession() - - if (res !== undefined) { - return res - } - } //* Fill session with user data const username = dbUser.username const role = dbUser.role