import http from "http"; import decrypt from "../../functions/dsql/decrypt"; import getAuthCookieNames from "../../functions/backend/cookies/get-auth-cookie-names"; import { checkAuthFile } from "../../functions/backend/auth/write-auth-files"; import parseCookies from "../../utils/backend/parseCookies"; import { AuthenticatedUser } from "../../types"; import getCsrfHeaderName from "../../actions/get-csrf-header-name"; import grabHostNames from "../../utils/grab-host-names"; const minuteInMilliseconds = 60000; const hourInMilliseconds = minuteInMilliseconds * 60; const dayInMilliseconds = hourInMilliseconds * 24; const weekInMilliseconds = dayInMilliseconds * 7; const monthInMilliseconds = dayInMilliseconds * 30; const yearInMilliseconds = dayInMilliseconds * 365; type Param = { request?: http.IncomingMessage & { [s: string]: any }; req?: http.IncomingMessage & { [s: string]: any }; cookieString?: string; encryptedUserString?: string; encryptionKey?: string; encryptionSalt?: string; level?: "deep" | "normal"; database?: string; dsqlUserId?: string | number; expiry?: number; csrfHeaderName?: string; debug?: boolean; }; /** * Authenticate User from request * ============================================================================== * @description This Function takes in a request object and returns a user object * with the user's data */ export default function userAuth({ request, req, encryptionKey, encryptionSalt, level, database, dsqlUserId, encryptedUserString, expiry = weekInMilliseconds, cookieString, csrfHeaderName, debug, }: Param): AuthenticatedUser { try { const finalRequest = req || request; const { user_id } = grabHostNames({ userId: dsqlUserId }); const cookies = parseCookies({ request: finalRequest, cookieString, }); if (debug) { console.log("userAuth:cookies:", cookies); } const keyNames = getAuthCookieNames({ userId: user_id, database: database || process.env.DSQL_DB_NAME, }); if (debug) { console.log("userAuth:keyNames:", keyNames); } const key = encryptedUserString ? encryptedUserString : cookies[keyNames.keyCookieName]; if (debug) { console.log("userAuth:key:", key); } /** * Grab the payload * * @description Grab the payload */ let userPayloadJSON = decrypt({ encryptedString: key, encryptionKey, encryptionSalt, }); if (debug) { console.log("userAuth:userPayloadJSON:", userPayloadJSON); } /** * Grab the payload * * @description Grab the payload */ if (!userPayloadJSON) { return { success: false, payload: null, msg: "Couldn't Decrypt cookie", cookieNames: keyNames, }; } /** * Grab the payload * * @description Grab the payload */ /** @type {import("../../types").DATASQUIREL_LoggedInUser} */ let userObject: import("../../types").DATASQUIREL_LoggedInUser = JSON.parse(userPayloadJSON); if (debug) { console.log("userAuth:userObject:", userObject); } if (!userObject.csrf_k) { return { success: false, payload: null, msg: "No CSRF_K in decrypted payload", cookieNames: keyNames, }; } if (!checkAuthFile(userObject.csrf_k)) { return { success: false, payload: null, msg: "Auth file doesn't exist", cookieNames: keyNames, }; } /** * Grab the payload * * @description Grab the payload */ if (level?.match(/deep/i) && finalRequest) { const finalCsrfHeaderName = csrfHeaderName || getCsrfHeaderName(); if ( finalRequest.headers[finalCsrfHeaderName] !== userObject.csrf_k ) { return { success: false, payload: null, msg: "CSRF_K mismatch", cookieNames: keyNames, }; } } const payloadCreationDate = Number(userObject.date); if ( Number.isNaN(payloadCreationDate) || typeof payloadCreationDate !== "number" ) { return { success: false, payload: null, msg: "Payload Creation Date is not a number", cookieNames: keyNames, }; } const timeElapsed = Date.now() - payloadCreationDate; const finalExpiry = process.env.DSQL_SESSION_EXPIRY_TIME ? Number(process.env.DSQL_SESSION_EXPIRY_TIME) : expiry; if (timeElapsed > finalExpiry) { return { success: false, payload: null, msg: "Session has expired", cookieNames: keyNames, }; } /** * Return User Object * * @description Return User Object */ return { success: true, payload: userObject, }; } catch (error: any) { global.ERROR_CALLBACK?.(`User Auth Error`, error as Error); /** * Return User Object * * @description Return User Object */ return { success: false, payload: null, msg: error.message, }; } }