refactor: centralize token configuration and update cookie handling in auth middleware and controllers

This commit is contained in:
Marco Pedone 2025-09-04 12:35:44 +02:00
parent 1aca72ac69
commit d5894f6ec4
5 changed files with 69 additions and 68 deletions

View file

@ -53,8 +53,8 @@ export const FormLogin = () => {
await utils.auth.getSession.invalidate();
setAlreadyRequested(true);
toast.success(t.auth.login.success);
//await router.push(redirect ? (redirect as string) : "/");
window.location.replace(redirect ? (redirect as string) : "/");
await router.push(redirect ? (redirect as string) : "/");
//window.location.replace(redirect ? (redirect as string) : "/");
},
});
const [altreadyRequested, setAlreadyRequested] = useState(false);

View file

@ -1,20 +1,19 @@
import { add } from "date-fns";
import { type NextRequest, NextResponse } from "next/server";
import { env } from "~/env.mjs";
import { TOKEN_CONFIG } from "~/server/auth/configs";
import {
ACCESS_TOKEN_COOKIE_NAME,
REFRESH_TOKEN_COOKIE_NAME,
signToken,
verifyToken,
} from "~/server/auth/jwt";
import { signToken, verifyToken } from "~/server/auth/jwt";
export const authMiddleware = async (req: NextRequest) => {
const path = req.nextUrl.pathname;
const refreshToken = req.cookies.get(REFRESH_TOKEN_COOKIE_NAME)?.value;
const refreshToken = req.cookies.get(
TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME,
)?.value;
const accessToken = req.cookies.get(ACCESS_TOKEN_COOKIE_NAME)?.value;
const accessToken = req.cookies.get(
TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME,
)?.value;
const isProtectedRoute =
(path.startsWith("/area-riservata") || path.startsWith("/servizio")) &&
@ -27,8 +26,8 @@ export const authMiddleware = async (req: NextRequest) => {
const destination = new URL("/login", req.nextUrl);
destination.searchParams.set("redirect", path);
const response = NextResponse.redirect(destination);
response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME);
response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME);
response.cookies.delete(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME);
response.cookies.delete(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME);
return response;
}
// if refresh token is present, handle refresh token logic
@ -42,7 +41,7 @@ export const authMiddleware = async (req: NextRequest) => {
const destination = new URL("/login", req.nextUrl);
destination.searchParams.set("redirect", path);
const response = NextResponse.redirect(destination);
response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME);
response.cookies.delete(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME);
return response;
}
@ -61,8 +60,8 @@ export const authMiddleware = async (req: NextRequest) => {
return await refreshAuthToken(req, refreshToken, true);
}
const response = NextResponse.next();
response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME);
response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME);
response.cookies.delete(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME);
response.cookies.delete(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME);
return response;
}
@ -88,7 +87,7 @@ export const authMiddleware = async (req: NextRequest) => {
const destination = new URL("/login", req.nextUrl);
destination.searchParams.set("redirect", path);
const response = NextResponse.redirect(destination);
response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME);
response.cookies.delete(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME);
return response;
}
if (path.startsWith("/auth/new-password-reset")) {
@ -121,7 +120,7 @@ const refreshAuthToken = async (
const destination = new URL("/login", req.nextUrl);
destination.searchParams.set("redirect", req.nextUrl.pathname);
const response = NextResponse.redirect(destination);
response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME);
response.cookies.delete(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME);
return response;
}
// If refresh token is valid, sign a new access token
@ -133,14 +132,14 @@ const refreshAuthToken = async (
const newAccessToken = await signToken(
refreshTokenPayload,
"5m",
TOKEN_CONFIG.ACCESS_TOKEN_EXPIRY,
"accessToken",
);
response.cookies.set(ACCESS_TOKEN_COOKIE_NAME, newAccessToken, {
expires: add(new Date(), { minutes: 1 }),
httpOnly: true,
path: "/",
sameSite: "lax",
response.cookies.set(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME, newAccessToken, {
expires: add(new Date(), {
minutes: TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_EXPIRY,
}),
...TOKEN_CONFIG.COOKIE_OPTIONS,
//secure: env.NODE_ENV === "production",
});
return response;

View file

@ -0,0 +1,13 @@
export const TOKEN_CONFIG = {
ACCESS_TOKEN_COOKIE_NAME: "access_token",
REFRESH_TOKEN_COOKIE_NAME: "refresh_token",
ACCESS_TOKEN_EXPIRY: "5m",
REFRESH_TOKEN_EXPIRY: "7d",
ACCESS_TOKEN_COOKIE_EXPIRY: 5,
REFRESH_TOKEN_COOKIE_EXPIRY: 7,
COOKIE_OPTIONS: {
httpOnly: true,
path: "/",
sameSite: "lax",
},
} as const;

View file

@ -3,9 +3,6 @@ import { jwtVerify, SignJWT } from "jose";
import { env } from "~/env.mjs";
import { type Session, sessionSchema } from "~/server/api/trpc";
export const ACCESS_TOKEN_COOKIE_NAME = "access_token";
export const REFRESH_TOKEN_COOKIE_NAME = "refresh_token";
const secret = new TextEncoder().encode(env.JWT_SECRET);
export async function signToken(

View file

@ -1,13 +1,9 @@
import { TRPCError } from "@trpc/server";
import { deleteCookie, type OptionsType, setCookie } from "cookies-next";
import { deleteCookie, setCookie } from "cookies-next";
import { add } from "date-fns";
import type { UsersId } from "~/schemas/public/Users";
import type { Context } from "~/server/api/trpc";
import {
ACCESS_TOKEN_COOKIE_NAME,
REFRESH_TOKEN_COOKIE_NAME,
signToken,
} from "~/server/auth/jwt";
import { signToken } from "~/server/auth/jwt";
import { db } from "~/server/db";
import { isBanned } from "~/server/services/banlist.service";
import {
@ -22,27 +18,7 @@ import {
findUser_byId_MINI,
} from "~/server/services/user.service";
import { checkCtx } from "~/server/utils/ctxChecker";
// [...] Cookie options
const cookieOptions: OptionsType = {
httpOnly: true,
path: "/",
sameSite: "lax",
//secure: env.NODE_ENV === "production",
};
const accessTokenExpiry = "1m";
export const refreshTokenExpiry = "5m";
const accessTokenCookieOptions: OptionsType = {
...cookieOptions,
expires: add(new Date(), { minutes: 1 }),
};
const refreshTokenCookieOptions: OptionsType = {
...cookieOptions,
expires: add(new Date(), { minutes: 5 }),
};
import { TOKEN_CONFIG } from "../auth/configs";
export const createUserAdmin = async ({
email,
@ -153,24 +129,30 @@ export const logIn = async ({
const accessToken = await signToken(
payload,
accessTokenExpiry,
TOKEN_CONFIG.ACCESS_TOKEN_EXPIRY,
"accessToken",
);
const refreshToken = await signToken(
payload,
refreshTokenExpiry,
TOKEN_CONFIG.REFRESH_TOKEN_EXPIRY,
"refreshToken",
);
console.log("Generated tokens for user:", user.email);
try {
await setCookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, {
...accessTokenCookieOptions,
await setCookie(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME, accessToken, {
...TOKEN_CONFIG.COOKIE_OPTIONS,
expires: add(new Date(), {
minutes: TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_EXPIRY,
}),
req,
res,
});
await setCookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
...refreshTokenCookieOptions,
await setCookie(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
...TOKEN_CONFIG.COOKIE_OPTIONS,
expires: add(new Date(), {
minutes: TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_EXPIRY,
}),
req,
res,
});
@ -209,21 +191,31 @@ export const swapAuth = async ({
});
}
const accessToken = await signToken(user, accessTokenExpiry, "accessToken");
const accessToken = await signToken(
user,
TOKEN_CONFIG.ACCESS_TOKEN_EXPIRY,
"accessToken",
);
const refreshToken = await signToken(
user,
refreshTokenExpiry,
TOKEN_CONFIG.REFRESH_TOKEN_EXPIRY,
"refreshToken",
);
// Send Access Token in Cookie
await setCookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, {
...accessTokenCookieOptions,
await setCookie(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME, accessToken, {
...TOKEN_CONFIG.COOKIE_OPTIONS,
expires: add(new Date(), {
minutes: TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_EXPIRY,
}),
req,
res,
});
await setCookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
...refreshTokenCookieOptions,
await setCookie(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
...TOKEN_CONFIG.COOKIE_OPTIONS,
expires: add(new Date(), {
minutes: TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_EXPIRY,
}),
req,
res,
});
@ -238,8 +230,8 @@ export const swapAuth = async ({
export const logOut = async ({ ctx: { req, res } }: { ctx: Context }) => {
checkCtx({ req, res });
try {
await deleteCookie(ACCESS_TOKEN_COOKIE_NAME, { req, res });
await deleteCookie(REFRESH_TOKEN_COOKIE_NAME, { req, res });
await deleteCookie(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME, { req, res });
await deleteCookie(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME, { req, res });
return { status: "success" };
} catch (err: unknown) {
console.error(err);