From 956836396bdec3e70287af1836990de5fa96be14 Mon Sep 17 00:00:00 2001 From: Laurent Maillet <35027619+lmaillet@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:24:47 +0100 Subject: [PATCH] fix(TDOPS-5926): set fetch credentials include (#5127) * TDOPS-5926: set fetch credentials include * TDOPS-5926: fix UT * TDOPS-5926: changeset * TDOPS-5926: update readme --- .changeset/strong-baboons-beam.md | 26 +++++++++++++ packages/cmf/README.md | 12 +++++- packages/cmf/__tests__/sagas/http.test.js | 45 ++++++++++------------- packages/cmf/src/sagas/http.js | 12 +++--- 4 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 .changeset/strong-baboons-beam.md diff --git a/.changeset/strong-baboons-beam.md b/.changeset/strong-baboons-beam.md new file mode 100644 index 00000000000..07eaefcb236 --- /dev/null +++ b/.changeset/strong-baboons-beam.md @@ -0,0 +1,26 @@ +--- +'@talend/babel-plugin-import-from-index': minor +'@talend/babel-plugin-assets-api': minor +'@talend/babel-plugin-import-d3': minor +'@talend/scripts-config-babel': minor +'@talend/scripts-config-cdn': minor +'@talend/react-faceted-search': minor +'@talend/storybook-docs': minor +'@talend/design-system': minor +'@talend/design-tokens': minor +'@talend/react-flow-designer': minor +'@talend/ui-storybook-one': minor +'@talend/design-docs': minor +'@talend/bootstrap-sass': minor +'@talend/react-components': minor +'@talend/react-containers': minor +'@talend/ui-playground': minor +'@talend/react-dataviz': minor +'@talend/react-stepper': minor +'@talend/react-forms': minor +'@talend/icons': minor +'@talend/bootstrap-theme': minor +'@talend/react-cmf': minor +--- + +Use include instead of same-origin in the credentials option of fetch. diff --git a/packages/cmf/README.md b/packages/cmf/README.md index 38a82900be0..d9ebacf0af8 100644 --- a/packages/cmf/README.md +++ b/packages/cmf/README.md @@ -156,9 +156,10 @@ We want testing experience to be easy so CMF provides some mocks for you. ```javascript import React from 'react'; -import { render, screen } from '@testing-library/react'; import { Provider } from 'react-cmf/lib/mock'; +import { render, screen } from '@testing-library/react'; + import AppMenu from './AppMenu.component'; describe('AppMenu', () => { @@ -184,6 +185,15 @@ you may change the following using simple props: - state - registry +## The http saga + +The [http saga](./src/sagas/index.md) is here to help execute some http requests from inside any saga. + +By default, the credentials option of fetch is set to `includes` and not the default `same-origin`. +It allows to share the credentials (cookies) in cross origin requests. + +See [credentials](https://developer.mozilla.org/en-US/docs/Web/API/fetch#credentials) in the fetch() global function for more details. + ## More - [App](https://github.com/Talend/ui/tree/master/packages/cmf/src/App.md) diff --git a/packages/cmf/__tests__/sagas/http.test.js b/packages/cmf/__tests__/sagas/http.test.js index 261a3457eb9..461ec5052a2 100644 --- a/packages/cmf/__tests__/sagas/http.test.js +++ b/packages/cmf/__tests__/sagas/http.test.js @@ -1,31 +1,31 @@ import { Headers, Response } from 'node-fetch'; import { call, put } from 'redux-saga/effects'; + +import interceptors from '../../src/httpInterceptors'; import { ACTION_TYPE_HTTP_ERRORS, HTTP_METHODS, HTTP_STATUS, } from '../../src/middlewares/http/constants'; -import interceptors from '../../src/httpInterceptors'; - import http, { + encodePayload, getDefaultConfig, handleBody, + handleDefaultHttpConfiguration, handleError, handleHttpResponse, - httpFetch, + HTTP, + httpDelete, HTTPError, - encodePayload, - wrapFetch, + httpFetch, httpGet, httpHead, - httpDelete, httpPatch, httpPost, httpPut, setDefaultConfig, setDefaultLanguage, - handleDefaultHttpConfiguration, - HTTP, + wrapFetch, } from '../../src/sagas/http'; const CSRFToken = 'hNjmdpuRgQClwZnb2c59F9gZhCi8jv9x'; @@ -282,7 +282,7 @@ describe('#handleHttpResponse', () => { new Response('{"foo": 42}', { status: HTTP_STATUS.OK, }), - { method: HTTP_METHODS.HEAD } + { method: HTTP_METHODS.HEAD }, ).then(({ data, response }) => { expect(data).toBe(''); expect(response instanceof Response).toBe(true); @@ -729,7 +729,7 @@ describe('#httpFetch', () => { type: 'some-documentation-uri', title: 'An expected error title', detail: 'Some useful detail', - code: 'business-error-xxx' + code: 'business-error-xxx', }; const payload = { bar: 42, @@ -904,7 +904,7 @@ describe('#httpFetch with CRSF token', () => { expect(fetch).toHaveBeenCalledWith(url, { body: '{"bar":42}', - credentials: 'same-origin', + credentials: 'include', headers: { Accept: 'application/json', 'Content-Type': 'application/json', @@ -927,17 +927,13 @@ describe('#httpFetch with CSRF handling configuration', () => { beforeAll(() => { HTTP.defaultConfig = null; - document.cookie = `${ - defaultHttpConfiguration.security.CSRFTokenCookieKey - }=${CSRFToken}; dwf_section_edit=True;`; + document.cookie = `${defaultHttpConfiguration.security.CSRFTokenCookieKey}=${CSRFToken}; dwf_section_edit=True;`; }); afterAll(() => { HTTP.defaultConfig = null; - document.cookie = `${ - defaultHttpConfiguration.security.CSRFTokenCookieKey - }=${CSRFToken}; dwf_section_edit=True; Max-Age=0`; + document.cookie = `${defaultHttpConfiguration.security.CSRFTokenCookieKey}=${CSRFToken}; dwf_section_edit=True; Max-Age=0`; }); it('check if httpFetch is called with the security configuration', done => { @@ -969,7 +965,7 @@ describe('#httpFetch with CSRF handling configuration', () => { expect(fetch).toHaveBeenCalledWith(url, { ...defaultHttpConfiguration, body: '{"bar":42}', - credentials: 'same-origin', + credentials: 'include', headers: { Accept: 'application/json', 'Content-Type': 'application/json', @@ -1011,7 +1007,7 @@ describe('#httpFetch', () => { expect(fetch).toHaveBeenCalledWith(url, { body: '{"bar":42}', - credentials: 'same-origin', + credentials: 'include', headers: { Accept: 'application/json', 'Content-Type': 'application/json', @@ -1052,7 +1048,7 @@ describe('#httpFetch', () => { expect(fetch).toHaveBeenCalledWith(url, { body: '{"bar":42}', - credentials: 'same-origin', + credentials: 'include', headers: { 'Accept-Language': 'fr', Accept: 'application/json', @@ -1086,7 +1082,7 @@ describe('#httpFetch', () => { expect(fetch).toHaveBeenCalledWith(url, { body: payload, - credentials: 'same-origin', + credentials: 'include', headers: { Accept: 'application/json', }, @@ -1121,7 +1117,7 @@ describe('#httpFetch', () => { expect(fetch).toHaveBeenCalledWith(url, { body: '{"bar":42}', - credentials: 'same-origin', + credentials: 'include', headers: { Accept: 'application/json', 'Content-Type': 'application/json', @@ -1379,9 +1375,8 @@ describe('handleDefaultConfiguration', () => { }, }; // when - const configuredHandleDefaultHttpConfiguration = handleDefaultHttpConfiguration( - defaultHttpConfig, - ); + const configuredHandleDefaultHttpConfiguration = + handleDefaultHttpConfiguration(defaultHttpConfig); configuredHandleDefaultHttpConfiguration(httpConfig); const resultTwo = configuredHandleDefaultHttpConfiguration({}); // expect diff --git a/packages/cmf/src/sagas/http.js b/packages/cmf/src/sagas/http.js index 6ba1639840b..c91b56f65e9 100644 --- a/packages/cmf/src/sagas/http.js +++ b/packages/cmf/src/sagas/http.js @@ -1,16 +1,16 @@ -import { call, put } from 'redux-saga/effects'; -import merge from 'lodash/merge'; -import get from 'lodash/get'; import curry from 'lodash/curry'; +import get from 'lodash/get'; +import merge from 'lodash/merge'; +import { call, put } from 'redux-saga/effects'; -import { mergeCSRFToken } from '../middlewares/http/csrfHandling'; +import interceptors from '../httpInterceptors'; import { ACTION_TYPE_HTTP_ERRORS, HTTP_METHODS, HTTP_STATUS, testHTTPCode, } from '../middlewares/http/constants'; -import interceptors from '../httpInterceptors'; +import { mergeCSRFToken } from '../middlewares/http/csrfHandling'; /** * Storage point for the doc setup using `setDefaultConfig` @@ -144,7 +144,7 @@ export function httpFetch(url, config, method, payload) { const params = merge( { - credentials: 'same-origin', + credentials: 'include', headers: defaultHeaders, method, },