diff --git a/src/core/plugins/auth/wrap-actions.js b/src/core/plugins/auth/wrap-actions.js index 4c4026069e2..a39775cf0d4 100644 --- a/src/core/plugins/auth/wrap-actions.js +++ b/src/core/plugins/auth/wrap-actions.js @@ -24,7 +24,11 @@ export const authorize = (oriAction, system) => (payload) => { const isApiKeyInCookie = isApiKeyAuth && isInCookie if (isApiKeyInCookie) { - document.cookie = `${schema.get("name")}=${value}; SameSite=None; Secure` + const secure = `${configs.url?.split("/")[0] === "https:" ? ";secure" : ""}` + const urlBasePath = configs.url?.split("/").splice(3).join("/") + const path = `${urlBasePath === undefined ? ";path=/" : ";path=/".concat(urlBasePath)}` + let cookieStr = `${schema.get("name")}=${value};samesite=None${secure}${path}` + document.cookie = cookieStr } } catch (error) { console.error( @@ -49,7 +53,9 @@ export const logout = (oriAction, system) => (payload) => { if (isApiKeyInCookie) { const cookieName = auth.getIn(["schema", "name"]) - document.cookie = `${cookieName}=; Max-Age=-99999999` + const urlBasePath = configs.url?.split("/").splice(3).join("/") + const path = `${urlBasePath === undefined ? ";path=/" : ";path=/".concat(urlBasePath)}` + document.cookie = `${cookieName}=;max-age=-99999999${path}` } }) } diff --git a/test/unit/core/plugins/auth/wrap-actions.js b/test/unit/core/plugins/auth/wrap-actions.js index cd1327d7be2..ed789518495 100644 --- a/test/unit/core/plugins/auth/wrap-actions.js +++ b/test/unit/core/plugins/auth/wrap-actions.js @@ -38,7 +38,107 @@ describe("Cookie based apiKey persistence in document.cookie", () => { authorize(jest.fn(), system)(payload) expect(document.cookie).toEqual( - "apiKeyCookie=test; SameSite=None; Secure" + "apiKeyCookie=test;samesite=None;path=/" + ) + }) + + it("should persist secure cookie in document.cookie for non-SSL targets", () => { + const system = { + getConfigs: () => ({ + persistAuthorization: true, + url: "http://example.org" + }), + } + const payload = { + api_key: { + schema: fromJS({ + type: "apiKey", + name: "apiKeyCookie", + in: "cookie", + }), + value: "test", + }, + } + + authorize(jest.fn(), system)(payload) + + expect(document.cookie).toEqual( + "apiKeyCookie=test;samesite=None;path=/" + ) + }) + + it("should persist secure cookie in document.cookie for SSL targets", () => { + const system = { + getConfigs: () => ({ + persistAuthorization: true, + url: "https://example.org" + }), + } + const payload = { + api_key: { + schema: fromJS({ + type: "apiKey", + name: "apiKeyCookie", + in: "cookie", + }), + value: "test", + }, + } + + authorize(jest.fn(), system)(payload) + + expect(document.cookie).toEqual( + "apiKeyCookie=test;samesite=None;secure;path=/" + ) + }) + + it("should persist secure cookie in document.cookie for non-root SSL targets", () => { + const system = { + getConfigs: () => ({ + persistAuthorization: true, + url: "https://example.org/api" + }), + } + const payload = { + api_key: { + schema: fromJS({ + type: "apiKey", + name: "apiKeyCookie", + in: "cookie", + }), + value: "test", + }, + } + + authorize(jest.fn(), system)(payload) + + expect(document.cookie).toEqual( + "apiKeyCookie=test;samesite=None;secure;path=/api" + ) + }) + + it("should persist secure cookie in document.cookie for SSL targets with non-root multi-level base path", () => { + const system = { + getConfigs: () => ({ + persistAuthorization: true, + url: "https://example.org/api/production" + }), + } + const payload = { + api_key: { + schema: fromJS({ + type: "apiKey", + name: "apiKeyCookie", + in: "cookie", + }), + value: "test", + }, + } + + authorize(jest.fn(), system)(payload) + + expect(document.cookie).toEqual( + "apiKeyCookie=test;samesite=None;secure;path=/api/production" ) }) @@ -64,7 +164,33 @@ describe("Cookie based apiKey persistence in document.cookie", () => { logout(jest.fn(), system)(["api_key"]) - expect(document.cookie).toEqual("apiKeyCookie=; Max-Age=-99999999") + expect(document.cookie).toEqual("apiKeyCookie=;max-age=-99999999;path=/") + }) + + it("should delete cookie from document.cookie for targets with non-root multi-level base path", () => { + const payload = fromJS({ + api_key: { + schema: { + type: "apiKey", + name: "apiKeyCookie", + in: "cookie", + }, + value: "test", + }, + }) + const system = { + getConfigs: () => ({ + persistAuthorization: true, + url: "https://example.org/api/production" + }), + authSelectors: { + authorized: () => payload, + }, + } + + logout(jest.fn(), system)(["api_key"]) + + expect(document.cookie).toEqual("apiKeyCookie=;max-age=-99999999;path=/api/production") }) }) @@ -116,4 +242,30 @@ describe("Cookie based apiKey persistence in document.cookie", () => { expect(document.cookie).toEqual("") }) }) + + it("should delete cookie from document.cookie for targets with non-root multi-level base path", () => { + const payload = fromJS({ + api_key: { + schema: { + type: "apiKey", + name: "apiKeyCookie", + in: "cookie", + }, + value: "test", + }, + }) + const system = { + getConfigs: () => ({ + persistAuthorization: false, + url: "https://example.org/api/production" + }), + authSelectors: { + authorized: () => payload, + }, + } + + logout(jest.fn(), system)(["api_key"]) + + expect(document.cookie).toEqual("") + }) })