From 486bb43e7814d2d41158d7ac848c80ddbc6519ec Mon Sep 17 00:00:00 2001 From: Praveen Kumar Upadhyay Date: Fri, 10 Apr 2026 12:10:22 +0530 Subject: [PATCH 1/4] [feat] Added the enabler for the cors issue for new header. --- lib/http/server/common/constant.js | 3 +++ lib/http/server/index.js | 2 +- lib/http/server/middleware/cors.js | 16 ++++++++++------ 3 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 lib/http/server/common/constant.js diff --git a/lib/http/server/common/constant.js b/lib/http/server/common/constant.js new file mode 100644 index 0000000..788b20a --- /dev/null +++ b/lib/http/server/common/constant.js @@ -0,0 +1,3 @@ +const REFRESH_TOKEN_HEADER = 'refresh' + +module.exports = { REFRESH_TOKEN_HEADER } diff --git a/lib/http/server/index.js b/lib/http/server/index.js index 27bb7ca..b5c8b95 100644 --- a/lib/http/server/index.js +++ b/lib/http/server/index.js @@ -42,7 +42,7 @@ class Server { if (corsOpt) { // cors will only be activated if provided with the option - app.use(cors(corsOpt.url, corsOpt.domain)) // func returns a valid middleware + app.use(cors({ url: corsOpt.url, domain: corsOpt.domain })) // func returns a valid middleware } if (swaggerOpt) { // only add the route if swagger option provided, else app dev should secure diff --git a/lib/http/server/middleware/cors.js b/lib/http/server/middleware/cors.js index a1c34e7..3e7795c 100644 --- a/lib/http/server/middleware/cors.js +++ b/lib/http/server/middleware/cors.js @@ -1,15 +1,17 @@ -const cors = require('cors') +const corsLib = require('cors') +const { REFRESH_TOKEN_HEADER } = require('../common/constant') class Cors { /** * Middleware to check for whitelist and allow API methods. + * Plus headers used for longer-session tenants (refresh token not only as HttpOnly cookie). */ - static cors (url, domain) { + static cors ({ url: urlList, domain }) { const corsOptions = { origin: function (origin, callback) { if (!origin) { callback(null) - } else if (url.indexOf(origin) !== -1) { + } else if (urlList.indexOf(origin) !== -1) { callback(null, true) } else { for (const d of domain) { @@ -28,11 +30,13 @@ class Cors { 'Content-Type', 'X-CSRF-Token', 'sentry-trace', - 'baggage' + 'baggage', + REFRESH_TOKEN_HEADER, + 'x-refresh-token' ], - exposedHeaders: ['link'] + exposedHeaders: ['link', REFRESH_TOKEN_HEADER] } - return cors(corsOptions) + return corsLib(corsOptions) } } From 10c693a327b1f39833dcb50ba0bde0fb4a0d128e Mon Sep 17 00:00:00 2001 From: Praveen Kumar Upadhyay Date: Fri, 10 Apr 2026 12:19:38 +0530 Subject: [PATCH 2/4] [feat] Added the comments for ligibility. --- lib/http/server/common/constant.js | 3 +++ lib/http/server/index.js | 4 ++-- lib/http/server/middleware/cors.js | 11 ++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/http/server/common/constant.js b/lib/http/server/common/constant.js index 788b20a..e349951 100644 --- a/lib/http/server/common/constant.js +++ b/lib/http/server/common/constant.js @@ -1,3 +1,6 @@ +// Request/response header name for the refresh token when it is not only carried in HttpOnly cookies. +// Used by the session retry flow: after the session or X-Auth expires, clients can send this header +// (and read an updated token from the same header on the response) to obtain a new session without a full re-login. const REFRESH_TOKEN_HEADER = 'refresh' module.exports = { REFRESH_TOKEN_HEADER } diff --git a/lib/http/server/index.js b/lib/http/server/index.js index b5c8b95..23fae8a 100644 --- a/lib/http/server/index.js +++ b/lib/http/server/index.js @@ -41,8 +41,8 @@ class Server { app.use(ratelimit(ratelimitOpt)) // call the static method to get the middleware if (corsOpt) { - // cors will only be activated if provided with the option - app.use(cors({ url: corsOpt.url, domain: corsOpt.domain })) // func returns a valid middleware + // Pass url + domain lists; Cors also whitelists refresh-token headers for session retry after expiry. + app.use(cors({ url: corsOpt.url, domain: corsOpt.domain })) } if (swaggerOpt) { // only add the route if swagger option provided, else app dev should secure diff --git a/lib/http/server/middleware/cors.js b/lib/http/server/middleware/cors.js index 3e7795c..ee9f3d9 100644 --- a/lib/http/server/middleware/cors.js +++ b/lib/http/server/middleware/cors.js @@ -3,8 +3,11 @@ const { REFRESH_TOKEN_HEADER } = require('../common/constant') class Cors { /** - * Middleware to check for whitelist and allow API methods. - * Plus headers used for longer-session tenants (refresh token not only as HttpOnly cookie). + * Returns Express CORS middleware: origin allowlist (exact URLs + domain suffixes), credentials, + * and headers needed for auth and observability. + * + * Includes the refresh-token header so browsers may send it on credentialed cross-origin requests + * during session retry (when session / X-Auth has expired and the client retries with a refresh token). */ static cors ({ url: urlList, domain }) { const corsOptions = { @@ -31,9 +34,11 @@ class Cors { 'X-CSRF-Token', 'sentry-trace', 'baggage', + // Session retry: preflight must allow clients to send the refresh token after session / X-Auth expiry. REFRESH_TOKEN_HEADER, - 'x-refresh-token' + 'x-refresh-token' // alternate casing/name some clients use ], + // Let frontend JS read a new refresh token from the response when the server issues one on retry. exposedHeaders: ['link', REFRESH_TOKEN_HEADER] } return corsLib(corsOptions) From dfabda90e61d9e48293da8c3401d2207cd51f228 Mon Sep 17 00:00:00 2001 From: Praveen Kumar Upadhyay Date: Fri, 10 Apr 2026 13:39:20 +0530 Subject: [PATCH 3/4] [feat] Refactored to remove the normal constant. --- lib/http/server/common/constant.js | 6 ------ lib/http/server/middleware/cors.js | 6 ++---- 2 files changed, 2 insertions(+), 10 deletions(-) delete mode 100644 lib/http/server/common/constant.js diff --git a/lib/http/server/common/constant.js b/lib/http/server/common/constant.js deleted file mode 100644 index e349951..0000000 --- a/lib/http/server/common/constant.js +++ /dev/null @@ -1,6 +0,0 @@ -// Request/response header name for the refresh token when it is not only carried in HttpOnly cookies. -// Used by the session retry flow: after the session or X-Auth expires, clients can send this header -// (and read an updated token from the same header on the response) to obtain a new session without a full re-login. -const REFRESH_TOKEN_HEADER = 'refresh' - -module.exports = { REFRESH_TOKEN_HEADER } diff --git a/lib/http/server/middleware/cors.js b/lib/http/server/middleware/cors.js index ee9f3d9..b8b22f5 100644 --- a/lib/http/server/middleware/cors.js +++ b/lib/http/server/middleware/cors.js @@ -1,5 +1,4 @@ const corsLib = require('cors') -const { REFRESH_TOKEN_HEADER } = require('../common/constant') class Cors { /** @@ -34,12 +33,11 @@ class Cors { 'X-CSRF-Token', 'sentry-trace', 'baggage', - // Session retry: preflight must allow clients to send the refresh token after session / X-Auth expiry. - REFRESH_TOKEN_HEADER, + 'refresh', 'x-refresh-token' // alternate casing/name some clients use ], // Let frontend JS read a new refresh token from the response when the server issues one on retry. - exposedHeaders: ['link', REFRESH_TOKEN_HEADER] + exposedHeaders: ['link', 'refresh'] } return corsLib(corsOptions) } From 6553a4a73f7bcbdd2bcb0e4397738ed4cff2578d Mon Sep 17 00:00:00 2001 From: Praveen Kumar Upadhyay Date: Fri, 10 Apr 2026 14:05:57 +0530 Subject: [PATCH 4/4] [feat] Exposed the alternate case aligned response header. --- lib/http/server/middleware/cors.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/http/server/middleware/cors.js b/lib/http/server/middleware/cors.js index b8b22f5..b4bfa6b 100644 --- a/lib/http/server/middleware/cors.js +++ b/lib/http/server/middleware/cors.js @@ -34,10 +34,11 @@ class Cors { 'sentry-trace', 'baggage', 'refresh', - 'x-refresh-token' // alternate casing/name some clients use + 'x-refresh-token' // alternate casing/name ], - // Let frontend JS read a new refresh token from the response when the server issues one on retry. - exposedHeaders: ['link', 'refresh'] + // Response header names JS may read on retry (only headers the server actually sets are visible). + // Include both if responses may use `refresh` or `x-refresh-token` for the new token. + exposedHeaders: ['link', 'refresh', 'x-refresh-token'] } return corsLib(corsOptions) }