Advertisement
djbob2000

Untitled

Jan 21st, 2025
16
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import { cookies } from "next/headers.js";
  2. import { getSession } from "@server/auth/session-db";
  3. import { lucia } from "@/fd/fd-toolbox/auth/lucia";
  4. import jwt from "jsonwebtoken";
  5. import { envSettingKeys } from "@root/infra/env-settings";
  6. import { Cookie } from "lucia";
  7. import { setCoreCache } from "@server/fd/fd-toolbox/cachings/core-memory-cache";
  8. import { fdCacheKeys } from "@server/fd/fd-toolbox-web/constants/fd-cache-keys";
  9. import { getNowAsString, parseStringEndDate } from "@/fd/fd-toolbox/dates/date-times";
  10.  
  11. interface SessionValidationResult {
  12.     userId: string;
  13.     workspaceId: string | null;
  14. }
  15.  
  16. interface SessionTokenPayload {
  17.     sessionId: string;
  18.     userId: string;
  19.     passwordHash: string;
  20.     workspaceId: string;
  21.     expires: string;
  22. }
  23.  
  24. const sessionConfig = {
  25.     durationInDays: 30,
  26.     secondsInDay: 24 * 60 * 60,
  27.     cookieOptions: {
  28.         httpOnly: true,
  29.         secure: true,
  30.         sameSite: "strict" as const,
  31.         path: "/",
  32.     },
  33. } as const;
  34.  
  35. const sessionDurationSeconds = sessionConfig.durationInDays * sessionConfig.secondsInDay;
  36.  
  37. const emptySessionValidationResult: SessionValidationResult = {
  38.     userId: null!,
  39.     workspaceId: null,
  40. };
  41.  
  42. const sessionTokenRequiredProperties = [
  43.     "sessionId",
  44.     "userId",
  45.     "passwordHash",
  46.     "workspaceId",
  47.     "expires",
  48. ] as const;
  49.  
  50. export function getSessionToken() {
  51.     const sessionCookie = cookies().get(lucia.sessionCookieName);
  52.     return sessionCookie?.value;
  53. }
  54.  
  55. export async function validateSessionToken(sessionToken: string) {
  56.     const session = await getSession(sessionToken);
  57.  
  58.     if (!session) {
  59.         await lucia.invalidateSession(sessionToken);
  60.         return emptySessionValidationResult;
  61.     }
  62.  
  63.     const result: SessionValidationResult = {
  64.         userId: session.userId,
  65.         workspaceId: session.workspaceId,
  66.     };
  67.  
  68.     return result;
  69. }
  70.  
  71. export function decodeSessionToken(token: string) {
  72.     try {
  73.         const decoded = jwt.verify(token, envSettingKeys.JwtKey);
  74.  
  75.         if (validateDecodedToken(decoded)) {
  76.             return extractSessionData(decoded);
  77.         }
  78.  
  79.         return null;
  80.     } catch (error) {
  81.         return null;
  82.     }
  83. }
  84.  
  85. export async function createSession(userId: string, workspaceId: string, passwordHash: string | undefined) {
  86.     const expiresDate = parseStringEndDate(getNowAsString(), sessionDurationSeconds);
  87.  
  88.     const session = await lucia.createSession(userId, { workspaceId });
  89.  
  90.     const sessionPayload = {
  91.         sessionId: session.id,
  92.         userId,
  93.         passwordHash,
  94.         workspaceId,
  95.         expires: expiresDate,
  96.     };
  97.  
  98.     const token = jwt.sign(sessionPayload, envSettingKeys.JwtKey, {
  99.         expiresIn: `${sessionConfig.durationInDays}d`,
  100.     });
  101.  
  102.     const sessionCookie = new Cookie(lucia.sessionCookieName, token, {
  103.         ...sessionConfig.cookieOptions,
  104.         expires: new Date(expiresDate),
  105.     });
  106.  
  107.     cookies().set(sessionCookie.name, sessionCookie.value, sessionCookie.attributes);
  108.  
  109.     setCoreCache(session.id, session, {
  110.         absoluteExpirationRelativeToNowSeconds: fdCacheKeys.secondsInFifteenMinutes,
  111.     });
  112.  
  113.     return { sessionCookie, session };
  114. }
  115.  
  116. function isObject(value: unknown): value is Record<string, unknown> {
  117.     return typeof value === "object" && value !== null;
  118. }
  119.  
  120. function validateDecodedToken(decoded: unknown): decoded is SessionTokenPayload {
  121.     if (!isObject(decoded)) return false;
  122.  
  123.     return sessionTokenRequiredProperties.every(
  124.         (prop) => prop in decoded && typeof decoded[prop] === "string",
  125.     );
  126. }
  127.  
  128. function extractSessionData(decoded: SessionTokenPayload) {
  129.     return {
  130.         sessionId: decoded.sessionId,
  131.         userId: decoded.userId,
  132.         passwordHash: decoded.passwordHash,
  133.         workspaceId: decoded.workspaceId,
  134.         expires: decoded.expires,
  135.     };
  136. }
  137.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement