From 91ff53d0692e736ffb6cb690430a66c25117d0e7 Mon Sep 17 00:00:00 2001 From: ThomasB Date: Tue, 22 Sep 2020 15:20:35 +0200 Subject: [PATCH 1/3] fix: correctly apply the proxy url to the Realm if it's set --- .../identityProviders/createGrant.js | 24 +++++++++++++++---- .../identityProviders/index.js | 21 ++++++++++++---- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/createIdentityProvider/identityProviders/createGrant.js b/src/createIdentityProvider/identityProviders/createGrant.js index 577bc1b..c264157 100644 --- a/src/createIdentityProvider/identityProviders/createGrant.js +++ b/src/createIdentityProvider/identityProviders/createGrant.js @@ -58,11 +58,25 @@ function defaultAuthorizationMethod({ .get(`${Realm}/integrations/proxy`, { headers: { Authorization }, }) - .then(({ data: response }) => ({ - Realm: response.data.url, - Authorization, - Expiration, - })) + .then(({ data: response }) => { + if ( + response.data && + response.data.settings && + response.data.settings.url + ) { + return { + Realm: response.data.settings.url, + Authorization, + Expiration, + } + } + + return { + Realm, + Authorization, + Expiration, + } + }) }) // Make sure to create a new access_token when the current one is going to expire diff --git a/src/createIdentityProvider/identityProviders/index.js b/src/createIdentityProvider/identityProviders/index.js index 3a8fb1f..83da742 100644 --- a/src/createIdentityProvider/identityProviders/index.js +++ b/src/createIdentityProvider/identityProviders/index.js @@ -56,10 +56,23 @@ export const IDPS = { .get(`${Realm}/integrations/proxy`, { headers: { Authorization }, }) - .then(({ data: response }) => ({ - Realm: response.data.url, - Authorization, - })) + .then(({ data: response }) => { + if ( + response.data && + response.data.settings && + response.data.settings.url + ) { + return { + Realm: response.data.settings.url, + Authorization, + } + } + + return { + Realm, + Authorization, + } + }) }) // Check if the identity call works for grant_type = token. This way we From 3a9d827ba67119387a644a42ec3830a6cd10636f Mon Sep 17 00:00:00 2001 From: ThomasB Date: Tue, 22 Sep 2020 16:32:22 +0200 Subject: [PATCH 2/3] test: support not mocking the proxy call --- src/build/Skedify.testing.js | 1 + test/mock.js | 24 +++++++++++++----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/build/Skedify.testing.js b/src/build/Skedify.testing.js index 99f2930..b64fbd9 100644 --- a/src/build/Skedify.testing.js +++ b/src/build/Skedify.testing.js @@ -22,6 +22,7 @@ export function installSkedifySDKMock(instance, options = {}) { Object.assign( { mockAccessTokensCall: true, + mockProxyCall: true, }, options ) diff --git a/test/mock.js b/test/mock.js index ddef4ca..d883e8b 100644 --- a/test/mock.js +++ b/test/mock.js @@ -103,20 +103,18 @@ const PROXY_CALL = { status: 200, data: { data: { - // We need to use a getter to delay the execution of this function - // We need access to the mostRecent request, but if there is no most recent - // Request we can't access its url. Therefor once we are sure the /integrations/proxy - // Is executed, we can safely run the mostRecent() function. - get url() { - return mostRecentRequest().url.replace('/integrations/proxy', '') + // We need to use a getter to delay the execution of this function + // We need access to the mostRecent request, but if there is no most recent + // Request we can't access its url. Therefor once we are sure the /integrations/proxy + // Is executed, we can safely run the mostRecent() function. + get url() { + return mostRecentRequest().url.replace('/integrations/proxy', '') + }, }, }, }, - }, } -const SETUP_REQUESTS = [{ ...ACCESS_TOKEN_CALL }, { ...PROXY_CALL }] - export function mockedRequests() { const { requests, ignoredRequests } = storage() @@ -126,9 +124,10 @@ export function mockedRequests() { } export function install(instance, options = {}) { - const { mockAccessTokensCall } = Object.assign( + const { mockAccessTokensCall, mockProxyCall } = Object.assign( { mockAccessTokensCall: true, + mockProxyCall: true, }, options ) @@ -143,7 +142,10 @@ export function install(instance, options = {}) { ignoredRequests: [], }) - const setup_calls = mockAccessTokensCall ? SETUP_REQUESTS : [PROXY_CALL] + const setup_calls = [ + ...(mockAccessTokensCall ? [ACCESS_TOKEN_CALL] : []), + ...(mockProxyCall ? [PROXY_CALL] : []), + ] // Stub setup requests setup_calls.forEach(({ url, response }) => { From ca09085945bb5cb9134000e595971e3762577ccf Mon Sep 17 00:00:00 2001 From: ThomasB Date: Tue, 22 Sep 2020 16:32:56 +0200 Subject: [PATCH 3/3] test: add tests for the proxy call which happens automatically --- src/Skedify.test.js | 100 +++++++++++++++++ src/__snapshots__/Skedify.test.js.snap | 150 +++++++++++++++++++++++++ test/mock.js | 2 + 3 files changed, 252 insertions(+) diff --git a/src/Skedify.test.js b/src/Skedify.test.js index 557e17c..e23dad6 100644 --- a/src/Skedify.test.js +++ b/src/Skedify.test.js @@ -643,6 +643,106 @@ describe('API', () => { expect(await matchRequest(SDK.subjects())).toMatchSnapshot() }) + it('should not use a proxy url when none is given', async () => { + const SDK2 = new API({ + auth_provider, + locale: 'nl-BE', + }) + + installSkedifySDKMock(SDK2, { mockProxyCall: false }) + + // No proxy url is returned + // Fallback/Default url should be used + mockMatchingURLResponse(/integrations/) + mockMatchingURLResponse(/subjects/, []) + + await SDK2.subjects() + + expect(mockedRequests()).toMatchSnapshot() + + uninstallSkedifySDKMock(SDK2) + }) + + it('should use the proxy url when given', async () => { + const SDK2 = new API({ + auth_provider, + locale: 'nl-BE', + }) + + installSkedifySDKMock(SDK2, { mockProxyCall: false }) + + // A proxy url is returned + // The proxy url should be used for the request + mockMatchingURLResponse(/integrations/, { + settings: { url: 'https://api-proxy.example.com' }, + }) + mockMatchingURLResponse(/subjects/, []) + + await SDK2.subjects() + + expect(mockedRequests()).toMatchSnapshot() + + uninstallSkedifySDKMock(SDK2) + }) + + it('should use the proxy url when given for the token grant', async () => { + const auth_provider_token = API.createAuthProviderString('token', { + token_type: 'Bearer', + access_token: 'some-access-token-goes-here', + realm: 'https://api.example.com', + }) + + const SDK2 = new API({ + auth_provider: auth_provider_token, + locale: 'nl-BE', + }) + + installSkedifySDKMock(SDK2, { mockProxyCall: false }) + + // A proxy url is returned + // The proxy url should be used for the request + mockMatchingURLResponse(/integrations/, { + settings: { url: 'https://api-proxy.example.com' }, + }) + // See grant/index.js + mockMatchingURLResponse(/identity/, []) + mockMatchingURLResponse(/subjects/, []) + + await SDK2.subjects() + + expect(mockedRequests()).toMatchSnapshot() + + uninstallSkedifySDKMock(SDK2) + }) + + it('should not use a proxy url when none is given for the token grant', async () => { + const auth_provider_token = API.createAuthProviderString('token', { + token_type: 'Bearer', + access_token: 'some-access-token-goes-here', + realm: 'https://api.example.com', + }) + + const SDK2 = new API({ + auth_provider: auth_provider_token, + locale: 'nl-BE', + }) + + installSkedifySDKMock(SDK2, { mockProxyCall: false }) + + // No proxy url is returned + // Fallback/Default url should be used + mockMatchingURLResponse(/integrations/) + // See grant/index.js + mockMatchingURLResponse(/identity/, []) + mockMatchingURLResponse(/subjects/, []) + + await SDK2.subjects() + + expect(mockedRequests()).toMatchSnapshot() + + uninstallSkedifySDKMock(SDK2) + }) + describe('API/Response', () => { it('should normalize the response when the call succeeds', async () => { mockResponse([]) diff --git a/src/__snapshots__/Skedify.test.js.snap b/src/__snapshots__/Skedify.test.js.snap index 67b67a1..33691f8 100644 --- a/src/__snapshots__/Skedify.test.js.snap +++ b/src/__snapshots__/Skedify.test.js.snap @@ -1461,6 +1461,81 @@ Object { } `; +exports[`API should not use a proxy url when none is given 1`] = ` +Array [ + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer fake_example_access_token", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api.example.com/integrations/proxy", + }, + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer fake_example_access_token", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api.example.com/subjects", + }, +] +`; + +exports[`API should not use a proxy url when none is given for the token grant 1`] = ` +Array [ + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer some-access-token-goes-here", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api.example.com/integrations/proxy", + }, + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer some-access-token-goes-here", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api.example.com/identity", + }, + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer some-access-token-goes-here", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api.example.com/subjects", + }, +] +`; + exports[`API should reflect configuration changes in the request (auth_provider) 1`] = ` Object { "data": undefined, @@ -1527,6 +1602,81 @@ Object { exports[`API should throw an error when an interceptor is added but it is not a function 1`] = `"[RESOURCE]: You tried to call \`.addResponseInterceptor(null)\` but it must receive a function."`; +exports[`API should use the proxy url when given 1`] = ` +Array [ + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer fake_example_access_token", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api.example.com/integrations/proxy", + }, + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer fake_example_access_token", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api-proxy.example.com/subjects", + }, +] +`; + +exports[`API should use the proxy url when given for the token grant 1`] = ` +Array [ + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer some-access-token-goes-here", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api.example.com/integrations/proxy", + }, + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer some-access-token-goes-here", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api-proxy.example.com/identity", + }, + Object { + "data": undefined, + "headers": Object { + "Accept": "application/json, text/plain, */*", + "Accept-Language": "nl-BE, nl;q=0.667, *;q=0.333", + "Authorization": "Bearer some-access-token-goes-here", + "Cache-Control": "no-store", + "Pragma": "no-cache", + }, + "method": "get", + "params": undefined, + "url": "https://api-proxy.example.com/subjects", + }, +] +`; + exports[`API/Auth Providers should be possible to use the \`public_client\` strategy 1`] = ` Object { "data": "my subjects data", diff --git a/test/mock.js b/test/mock.js index d883e8b..f0fcf80 100644 --- a/test/mock.js +++ b/test/mock.js @@ -103,6 +103,7 @@ const PROXY_CALL = { status: 200, data: { data: { + settings: { // We need to use a getter to delay the execution of this function // We need access to the mostRecent request, but if there is no most recent // Request we can't access its url. Therefor once we are sure the /integrations/proxy @@ -113,6 +114,7 @@ const PROXY_CALL = { }, }, }, + }, } export function mockedRequests() {