From 0880526f44f23bec973ea777fd4f37160c48ffbe Mon Sep 17 00:00:00 2001 From: Benjamin Toby Date: Sat, 14 Dec 2024 16:23:16 +0100 Subject: [PATCH] Updates --- client/fetch/index.d.ts | 2 +- client/fetch/index.js | 2 +- package-shared/types/index.d.ts | 2 +- package-shared/types/index.ts | 2 +- package.json | 2 +- users/user-auth.d.ts | 6 +++++- users/user-auth.js | 13 +++++++++++-- 7 files changed, 21 insertions(+), 8 deletions(-) diff --git a/client/fetch/index.d.ts b/client/fetch/index.d.ts index b65b1df..fddf1ee 100644 --- a/client/fetch/index.d.ts +++ b/client/fetch/index.d.ts @@ -1,5 +1,5 @@ export = clientFetch; -declare function clientFetch(url: string, options?: import("../../package-shared/types").FetchApiOptions, contentType?: "json" | "text" | "html" | "blob" | "file"): Promise; +declare function clientFetch(url: string, options?: import("../../package-shared/types").FetchApiOptions, csrf?: boolean): Promise; declare namespace clientFetch { export { clientFetch as fetchApi }; } diff --git a/client/fetch/index.js b/client/fetch/index.js index fc1c006..f6a141d 100644 --- a/client/fetch/index.js +++ b/client/fetch/index.js @@ -3,7 +3,7 @@ const _ = require("lodash"); /** @type {import("../../package-shared/types").FetchApiFn} */ -async function clientFetch(url, options, contentType) { +async function clientFetch(url, options, csrf) { let data; let finalUrl = url; diff --git a/package-shared/types/index.d.ts b/package-shared/types/index.d.ts index 9b91c91..7448c00 100644 --- a/package-shared/types/index.d.ts +++ b/package-shared/types/index.d.ts @@ -885,7 +885,7 @@ export type CheckApiCredentialsFnParam = { table?: string; user_id?: string | number; }; -export type FetchApiFn = (url: string, options?: FetchApiOptions, contentType?: "json" | "text" | "html" | "blob" | "file") => Promise; +export type FetchApiFn = (url: string, options?: FetchApiOptions, csrf?: boolean) => Promise; export type FetchApiOptions = RequestInit & { method: "POST" | "GET" | "DELETE" | "PUT" | "PATCH" | "post" | "get" | "delete" | "put" | "patch"; body?: object | string; diff --git a/package-shared/types/index.ts b/package-shared/types/index.ts index 6856e02..e04e8b5 100644 --- a/package-shared/types/index.ts +++ b/package-shared/types/index.ts @@ -1049,7 +1049,7 @@ export type CheckApiCredentialsFnParam = { export type FetchApiFn = ( url: string, options?: FetchApiOptions, - contentType?: "json" | "text" | "html" | "blob" | "file" + csrf?: boolean ) => Promise; export type FetchApiOptions = RequestInit & { diff --git a/package.json b/package.json index db27d51..906615a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@moduletrace/datasquirel", - "version": "3.1.2", + "version": "3.1.3", "description": "Cloud-based SQL data management tool", "main": "index.js", "bin": { diff --git a/users/user-auth.d.ts b/users/user-auth.d.ts index 1857827..1e44a8d 100644 --- a/users/user-auth.d.ts +++ b/users/user-auth.d.ts @@ -16,10 +16,12 @@ export = userAuth; * @param {string} [params.database] - Database Name (slug) * @param {string | number} [params.dsqlUserId] - alt env: DSQL_API_USER_ID * @param {number} [params.expiry] - Expiry time in milliseconds + * @param {string} [params.csrfHeaderName] - Optional. CSRF Header Name + * @param {boolean} [params.csrfHeaderIsValue] - If the csrf value is the name of the request http header * * @returns { import("../package-shared/types").AuthenticatedUser } */ -declare function userAuth({ request, req, encryptionKey, encryptionSalt, level, database, dsqlUserId, encryptedUserString, expiry, cookieString, }: { +declare function userAuth({ request, req, encryptionKey, encryptionSalt, level, database, dsqlUserId, encryptedUserString, expiry, cookieString, csrfHeaderIsValue, csrfHeaderName, }: { request?: http.IncomingMessage & { [x: string]: any; }; @@ -34,5 +36,7 @@ declare function userAuth({ request, req, encryptionKey, encryptionSalt, level, database?: string; dsqlUserId?: string | number; expiry?: number; + csrfHeaderName?: string; + csrfHeaderIsValue?: boolean; }): import("../package-shared/types").AuthenticatedUser; import http = require("http"); diff --git a/users/user-auth.js b/users/user-auth.js index 0fc416a..9fe0863 100644 --- a/users/user-auth.js +++ b/users/user-auth.js @@ -32,6 +32,8 @@ const yearInMilliseconds = dayInMilliseconds * 365; * @param {string} [params.database] - Database Name (slug) * @param {string | number} [params.dsqlUserId] - alt env: DSQL_API_USER_ID * @param {number} [params.expiry] - Expiry time in milliseconds + * @param {string} [params.csrfHeaderName] - Optional. CSRF Header Name + * @param {boolean} [params.csrfHeaderIsValue] - If the csrf value is the name of the request http header * * @returns { import("../package-shared/types").AuthenticatedUser } */ @@ -46,6 +48,8 @@ function userAuth({ encryptedUserString, expiry = weekInMilliseconds, cookieString, + csrfHeaderIsValue, + csrfHeaderName, }) { try { const finalEncryptionKey = @@ -127,12 +131,17 @@ function userAuth({ */ if ( level?.match(/deep/i) && - !csrf?.match(new RegExp(`${userObject.csrf_k}`)) + ((csrfHeaderName && + req?.headers[csrfHeaderName] !== userObject.csrf_k && + request?.headers[csrfHeaderName] !== userObject.csrf_k) || + (csrfHeaderIsValue && + !req?.headers[userObject.csrf_k] && + !request?.headers[userObject.csrf_k])) ) { return { success: false, payload: null, - msg: "CSRF_K requested but does not match payload", + msg: "CSRF_K mismatch", }; }