refactor: centralize token configuration and update cookie handling in auth middleware and controllers
This commit is contained in:
parent
1aca72ac69
commit
d5894f6ec4
5 changed files with 69 additions and 68 deletions
|
|
@ -53,8 +53,8 @@ export const FormLogin = () => {
|
||||||
await utils.auth.getSession.invalidate();
|
await utils.auth.getSession.invalidate();
|
||||||
setAlreadyRequested(true);
|
setAlreadyRequested(true);
|
||||||
toast.success(t.auth.login.success);
|
toast.success(t.auth.login.success);
|
||||||
//await router.push(redirect ? (redirect as string) : "/");
|
await router.push(redirect ? (redirect as string) : "/");
|
||||||
window.location.replace(redirect ? (redirect as string) : "/");
|
//window.location.replace(redirect ? (redirect as string) : "/");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const [altreadyRequested, setAlreadyRequested] = useState(false);
|
const [altreadyRequested, setAlreadyRequested] = useState(false);
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,19 @@
|
||||||
import { add } from "date-fns";
|
import { add } from "date-fns";
|
||||||
import { type NextRequest, NextResponse } from "next/server";
|
import { type NextRequest, NextResponse } from "next/server";
|
||||||
import { env } from "~/env.mjs";
|
import { TOKEN_CONFIG } from "~/server/auth/configs";
|
||||||
|
|
||||||
import {
|
import { signToken, verifyToken } from "~/server/auth/jwt";
|
||||||
ACCESS_TOKEN_COOKIE_NAME,
|
|
||||||
REFRESH_TOKEN_COOKIE_NAME,
|
|
||||||
signToken,
|
|
||||||
verifyToken,
|
|
||||||
} from "~/server/auth/jwt";
|
|
||||||
|
|
||||||
export const authMiddleware = async (req: NextRequest) => {
|
export const authMiddleware = async (req: NextRequest) => {
|
||||||
const path = req.nextUrl.pathname;
|
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 =
|
const isProtectedRoute =
|
||||||
(path.startsWith("/area-riservata") || path.startsWith("/servizio")) &&
|
(path.startsWith("/area-riservata") || path.startsWith("/servizio")) &&
|
||||||
|
|
@ -27,8 +26,8 @@ export const authMiddleware = async (req: NextRequest) => {
|
||||||
const destination = new URL("/login", req.nextUrl);
|
const destination = new URL("/login", req.nextUrl);
|
||||||
destination.searchParams.set("redirect", path);
|
destination.searchParams.set("redirect", path);
|
||||||
const response = NextResponse.redirect(destination);
|
const response = NextResponse.redirect(destination);
|
||||||
response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME);
|
response.cookies.delete(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME);
|
||||||
response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME);
|
response.cookies.delete(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
// if refresh token is present, handle refresh token logic
|
// 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);
|
const destination = new URL("/login", req.nextUrl);
|
||||||
destination.searchParams.set("redirect", path);
|
destination.searchParams.set("redirect", path);
|
||||||
const response = NextResponse.redirect(destination);
|
const response = NextResponse.redirect(destination);
|
||||||
response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME);
|
response.cookies.delete(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,8 +60,8 @@ export const authMiddleware = async (req: NextRequest) => {
|
||||||
return await refreshAuthToken(req, refreshToken, true);
|
return await refreshAuthToken(req, refreshToken, true);
|
||||||
}
|
}
|
||||||
const response = NextResponse.next();
|
const response = NextResponse.next();
|
||||||
response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME);
|
response.cookies.delete(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME);
|
||||||
response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME);
|
response.cookies.delete(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +87,7 @@ export const authMiddleware = async (req: NextRequest) => {
|
||||||
const destination = new URL("/login", req.nextUrl);
|
const destination = new URL("/login", req.nextUrl);
|
||||||
destination.searchParams.set("redirect", path);
|
destination.searchParams.set("redirect", path);
|
||||||
const response = NextResponse.redirect(destination);
|
const response = NextResponse.redirect(destination);
|
||||||
response.cookies.delete(ACCESS_TOKEN_COOKIE_NAME);
|
response.cookies.delete(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
if (path.startsWith("/auth/new-password-reset")) {
|
if (path.startsWith("/auth/new-password-reset")) {
|
||||||
|
|
@ -121,7 +120,7 @@ const refreshAuthToken = async (
|
||||||
const destination = new URL("/login", req.nextUrl);
|
const destination = new URL("/login", req.nextUrl);
|
||||||
destination.searchParams.set("redirect", req.nextUrl.pathname);
|
destination.searchParams.set("redirect", req.nextUrl.pathname);
|
||||||
const response = NextResponse.redirect(destination);
|
const response = NextResponse.redirect(destination);
|
||||||
response.cookies.delete(REFRESH_TOKEN_COOKIE_NAME);
|
response.cookies.delete(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
// If refresh token is valid, sign a new access token
|
// If refresh token is valid, sign a new access token
|
||||||
|
|
@ -133,14 +132,14 @@ const refreshAuthToken = async (
|
||||||
|
|
||||||
const newAccessToken = await signToken(
|
const newAccessToken = await signToken(
|
||||||
refreshTokenPayload,
|
refreshTokenPayload,
|
||||||
"5m",
|
TOKEN_CONFIG.ACCESS_TOKEN_EXPIRY,
|
||||||
"accessToken",
|
"accessToken",
|
||||||
);
|
);
|
||||||
response.cookies.set(ACCESS_TOKEN_COOKIE_NAME, newAccessToken, {
|
response.cookies.set(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME, newAccessToken, {
|
||||||
expires: add(new Date(), { minutes: 1 }),
|
expires: add(new Date(), {
|
||||||
httpOnly: true,
|
minutes: TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_EXPIRY,
|
||||||
path: "/",
|
}),
|
||||||
sameSite: "lax",
|
...TOKEN_CONFIG.COOKIE_OPTIONS,
|
||||||
//secure: env.NODE_ENV === "production",
|
//secure: env.NODE_ENV === "production",
|
||||||
});
|
});
|
||||||
return response;
|
return response;
|
||||||
|
|
|
||||||
13
apps/infoalloggi/src/server/auth/configs.ts
Normal file
13
apps/infoalloggi/src/server/auth/configs.ts
Normal 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;
|
||||||
|
|
@ -3,9 +3,6 @@ import { jwtVerify, SignJWT } from "jose";
|
||||||
import { env } from "~/env.mjs";
|
import { env } from "~/env.mjs";
|
||||||
import { type Session, sessionSchema } from "~/server/api/trpc";
|
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);
|
const secret = new TextEncoder().encode(env.JWT_SECRET);
|
||||||
|
|
||||||
export async function signToken(
|
export async function signToken(
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,9 @@
|
||||||
import { TRPCError } from "@trpc/server";
|
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 { add } from "date-fns";
|
||||||
import type { UsersId } from "~/schemas/public/Users";
|
import type { UsersId } from "~/schemas/public/Users";
|
||||||
import type { Context } from "~/server/api/trpc";
|
import type { Context } from "~/server/api/trpc";
|
||||||
import {
|
import { signToken } from "~/server/auth/jwt";
|
||||||
ACCESS_TOKEN_COOKIE_NAME,
|
|
||||||
REFRESH_TOKEN_COOKIE_NAME,
|
|
||||||
signToken,
|
|
||||||
} from "~/server/auth/jwt";
|
|
||||||
import { db } from "~/server/db";
|
import { db } from "~/server/db";
|
||||||
import { isBanned } from "~/server/services/banlist.service";
|
import { isBanned } from "~/server/services/banlist.service";
|
||||||
import {
|
import {
|
||||||
|
|
@ -22,27 +18,7 @@ import {
|
||||||
findUser_byId_MINI,
|
findUser_byId_MINI,
|
||||||
} from "~/server/services/user.service";
|
} from "~/server/services/user.service";
|
||||||
import { checkCtx } from "~/server/utils/ctxChecker";
|
import { checkCtx } from "~/server/utils/ctxChecker";
|
||||||
|
import { TOKEN_CONFIG } from "../auth/configs";
|
||||||
// [...] 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 }),
|
|
||||||
};
|
|
||||||
|
|
||||||
export const createUserAdmin = async ({
|
export const createUserAdmin = async ({
|
||||||
email,
|
email,
|
||||||
|
|
@ -153,24 +129,30 @@ export const logIn = async ({
|
||||||
|
|
||||||
const accessToken = await signToken(
|
const accessToken = await signToken(
|
||||||
payload,
|
payload,
|
||||||
accessTokenExpiry,
|
TOKEN_CONFIG.ACCESS_TOKEN_EXPIRY,
|
||||||
"accessToken",
|
"accessToken",
|
||||||
);
|
);
|
||||||
const refreshToken = await signToken(
|
const refreshToken = await signToken(
|
||||||
payload,
|
payload,
|
||||||
refreshTokenExpiry,
|
TOKEN_CONFIG.REFRESH_TOKEN_EXPIRY,
|
||||||
"refreshToken",
|
"refreshToken",
|
||||||
);
|
);
|
||||||
console.log("Generated tokens for user:", user.email);
|
console.log("Generated tokens for user:", user.email);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await setCookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, {
|
await setCookie(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME, accessToken, {
|
||||||
...accessTokenCookieOptions,
|
...TOKEN_CONFIG.COOKIE_OPTIONS,
|
||||||
|
expires: add(new Date(), {
|
||||||
|
minutes: TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_EXPIRY,
|
||||||
|
}),
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
});
|
});
|
||||||
await setCookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
|
await setCookie(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
|
||||||
...refreshTokenCookieOptions,
|
...TOKEN_CONFIG.COOKIE_OPTIONS,
|
||||||
|
expires: add(new Date(), {
|
||||||
|
minutes: TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_EXPIRY,
|
||||||
|
}),
|
||||||
req,
|
req,
|
||||||
res,
|
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(
|
const refreshToken = await signToken(
|
||||||
user,
|
user,
|
||||||
refreshTokenExpiry,
|
TOKEN_CONFIG.REFRESH_TOKEN_EXPIRY,
|
||||||
"refreshToken",
|
"refreshToken",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Send Access Token in Cookie
|
// Send Access Token in Cookie
|
||||||
await setCookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, {
|
await setCookie(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME, accessToken, {
|
||||||
...accessTokenCookieOptions,
|
...TOKEN_CONFIG.COOKIE_OPTIONS,
|
||||||
|
expires: add(new Date(), {
|
||||||
|
minutes: TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_EXPIRY,
|
||||||
|
}),
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
});
|
});
|
||||||
await setCookie(REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
|
await setCookie(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME, refreshToken, {
|
||||||
...refreshTokenCookieOptions,
|
...TOKEN_CONFIG.COOKIE_OPTIONS,
|
||||||
|
expires: add(new Date(), {
|
||||||
|
minutes: TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_EXPIRY,
|
||||||
|
}),
|
||||||
req,
|
req,
|
||||||
res,
|
res,
|
||||||
});
|
});
|
||||||
|
|
@ -238,8 +230,8 @@ export const swapAuth = async ({
|
||||||
export const logOut = async ({ ctx: { req, res } }: { ctx: Context }) => {
|
export const logOut = async ({ ctx: { req, res } }: { ctx: Context }) => {
|
||||||
checkCtx({ req, res });
|
checkCtx({ req, res });
|
||||||
try {
|
try {
|
||||||
await deleteCookie(ACCESS_TOKEN_COOKIE_NAME, { req, res });
|
await deleteCookie(TOKEN_CONFIG.ACCESS_TOKEN_COOKIE_NAME, { req, res });
|
||||||
await deleteCookie(REFRESH_TOKEN_COOKIE_NAME, { req, res });
|
await deleteCookie(TOKEN_CONFIG.REFRESH_TOKEN_COOKIE_NAME, { req, res });
|
||||||
return { status: "success" };
|
return { status: "success" };
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue