Skip to content

Commit

Permalink
feat(sdk) remove pkce option becuase all OAuth flows must use PKCE
Browse files Browse the repository at this point in the history
  • Loading branch information
mt-dfrey committed Oct 6, 2023
1 parent 3099aee commit 2234e0e
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 75 deletions.
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module.exports = {
// https://github.com/facebook/jest/issues/2070#issuecomment-431706685
'<rootDir>/.*/__mocks__'
],
testPathIgnorePatterns: ['/__tests__/helper/'],
globals: {
__VERSION__: packageJSON.version
}
Expand Down
3 changes: 0 additions & 3 deletions sample/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ elements.authorizeBtn.onclick = () => {
authorizeOptions.scopes = scopesSelectedOptions.map((x) => x.value);
}

authorizeOptions.pkce = true;

mtLinkSdk.authorize(authorizeOptions);
};

Expand All @@ -75,7 +73,6 @@ elements.doOnboardBtn.onclick = async () => {
}

onBoardOptions.email = onboardOptionsElms.email.value;
onBoardOptions.pkce = true;

mtLinkSdk.onboard(onBoardOptions);
} catch (error) {
Expand Down
21 changes: 21 additions & 0 deletions src/__tests__/helper/expect-url-to-match.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import qs from 'qs';

export interface UrlExpectation {
baseUrl: string;
path: string;
query?: Record<string, string>;
}

export default function expectUrlToMatchWithPKCE(actual: URL | string, expectation: UrlExpectation) {
const url = typeof actual === 'string' ? new URL(actual) : actual;
const actualQuery = qs.parse(new URLSearchParams(url.search).toString());

expect(actualQuery.code_challenge).toBeDefined();
delete actualQuery.code_challenge; // ignore PKCE code challenge because it's randomly generated
expect(actualQuery.code_challenge_method).toBe('S256');
delete actualQuery.code_challenge_method;

expect(url.pathname).toBe(expectation.path);
expect(`${url.protocol}//${url.hostname}`).toBe(expectation.baseUrl);
expect(actualQuery).toEqual(expectation.query || {});
}
32 changes: 22 additions & 10 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import tokenInfo from '../api/token-info';
import mtLinkSdk, { Mode, MtLinkSdk } from '..';

import packageJson from '../../package.json';
import expectUrlToMatchWithPKCE from './helper/expect-url-to-match';

jest.mock('../api/authorize');
jest.mock('../api/onboard');
Expand Down Expand Up @@ -80,19 +81,30 @@ describe('index', () => {

const sdkVersion = packageJson.version;

const authQuery = {
client_id: 'clientId',
response_type: 'code',
scope: 'scopes',
redirect_uri: 'redirectUri',
country: 'JP',
configs: `authn_method=sso&sdk_platform=js&sdk_version=${sdkVersion}`
}
const result8 = instance.authorizeUrl({ scopes: 'scopes' });
expect(result8).toBe(
'https://myaccount.getmoneytree.com/oauth/authorize?client_id=clientId&response_type=code&' +
'scope=scopes&redirect_uri=redirectUri&country=JP&saml_subject_id=samlSubjectId&' +
`configs=authn_method%3Dsso%26sdk_platform%3Djs%26sdk_version%3D${sdkVersion}`
);
expectUrlToMatchWithPKCE(result8, {
baseUrl: 'https://myaccount.getmoneytree.com',
path: '/oauth/authorize',
query: {
...authQuery,
saml_subject_id: 'samlSubjectId',
}
})

const result9 = instance.onboardUrl({ scopes: 'scopes' });
expect(result9).toBe(
'https://myaccount.getmoneytree.com/onboard?client_id=clientId&response_type=code&' +
'scope=scopes&redirect_uri=redirectUri&country=JP&' +
`configs=authn_method%3Dsso%26sdk_platform%3Djs%26sdk_version%3D${sdkVersion}`
);
expectUrlToMatchWithPKCE(result9, {
baseUrl: 'https://myaccount.getmoneytree.com',
path: '/onboard',
query: authQuery
})

const result10 = instance.logoutUrl({ backTo: 'backTo' });
expect(result10).toBe(
Expand Down
15 changes: 7 additions & 8 deletions src/api/__tests__/authorize-url.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import qs from 'qs';
import { mocked } from 'ts-jest/utils';

import { MY_ACCOUNT_DOMAINS } from '../../server-paths';
import { MtLinkSdk } from '../..';
import authorizeUrl from '../authorize-url';
import { generateConfigs } from '../../helper';
import storage from '../../storage';
import expectUrlToMatchWithPKCE from '../../__tests__/helper/expect-url-to-match';

jest.mock('../../storage');

Expand Down Expand Up @@ -53,7 +53,7 @@ describe('api', () => {

const url = authorizeUrl(mtLinkSdk.storedOptions);

const query = qs.stringify({
const query = {
client_id: clientId,
cobrand_client_id: cobrandClientId,
response_type: 'code',
Expand All @@ -63,9 +63,8 @@ describe('api', () => {
locale,
saml_subject_id: samlSubjectId,
configs: generateConfigs()
});

expect(url).toBe(`${MY_ACCOUNT_DOMAINS.production}/oauth/authorize?${query}`);
};
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/oauth/authorize', query})
});

test('with options', () => {
Expand All @@ -85,7 +84,7 @@ describe('api', () => {
scopes
});

const query = qs.stringify({
const query = {
client_id: clientId,
response_type: 'code',
scope: scopes,
Expand All @@ -94,8 +93,8 @@ describe('api', () => {
country,
saml_subject_id: samlSubjectId,
configs: generateConfigs()
});
expect(url).toBe(`${MY_ACCOUNT_DOMAINS.production}/oauth/authorize?${query}`);
}
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/oauth/authorize', query})
});
});
});
22 changes: 11 additions & 11 deletions src/api/__tests__/authorize.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import qs from 'qs';
import { mocked } from 'ts-jest/utils';

import { MY_ACCOUNT_DOMAINS } from '../../server-paths';
import { MtLinkSdk } from '../..';
import authorize from '../authorize';
import { generateConfigs } from '../../helper';
import storage from '../../storage';
import expectUrlToMatchWithPKCE from '../../__tests__/helper/expect-url-to-match';

jest.mock('../../storage');

Expand Down Expand Up @@ -57,8 +57,9 @@ describe('api', () => {
authorize(mtLinkSdk.storedOptions);

expect(open).toBeCalledTimes(1);

const query = qs.stringify({
expect(open).toBeCalledWith(expect.any(String), '_self', 'noreferrer');
const url = open.mock.calls[0][0]
const query = {
client_id: clientId,
cobrand_client_id: cobrandClientId,
response_type: 'code',
Expand All @@ -68,9 +69,8 @@ describe('api', () => {
locale,
saml_subject_id: samlSubjectId,
configs: generateConfigs()
});
const url = `${MY_ACCOUNT_DOMAINS.production}/oauth/authorize?${query}`;
expect(open).toBeCalledWith(url, '_self', 'noreferrer');
};
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/oauth/authorize', query })
});

test('with options', () => {
Expand All @@ -92,8 +92,9 @@ describe('api', () => {
});

expect(open).toBeCalledTimes(1);

const query = qs.stringify({
expect(open).toBeCalledWith(expect.any(String), '_self', 'noreferrer');
const url = open.mock.calls[0][0]
const query = {
client_id: clientId,
response_type: 'code',
scope: scopes,
Expand All @@ -102,9 +103,8 @@ describe('api', () => {
country,
saml_subject_id: samlSubjectId,
configs: generateConfigs()
});
const url = `${MY_ACCOUNT_DOMAINS.production}/oauth/authorize?${query}`;
expect(open).toBeCalledWith(url, '_self', 'noreferrer');
};
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/oauth/authorize', query })
});

test('without window', () => {
Expand Down
24 changes: 13 additions & 11 deletions src/api/__tests__/onboard-url.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MtLinkSdk } from '../..';
import onboardUrl from '../onboard-url';
import { generateConfigs } from '../../helper';
import storage from '../../storage';
import expectUrlToMatchWithPKCE from '../../__tests__/helper/expect-url-to-match';

jest.mock('../../storage');

Expand Down Expand Up @@ -53,7 +54,7 @@ describe('api', () => {

const url = onboardUrl(mtLinkSdk.storedOptions);

const query = qs.stringify({
const query = {
client_id: clientId,
cobrand_client_id: cobrandClientId,
response_type: 'code',
Expand All @@ -62,9 +63,9 @@ describe('api', () => {
country,
locale,
configs: generateConfigs({ email })
});
};

expect(url).toBe(`${MY_ACCOUNT_DOMAINS.production}/onboard?${query}`);
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/onboard', query: query })
});

test('with options', () => {
Expand All @@ -78,23 +79,24 @@ describe('api', () => {
mtLinkSdk.init(clientId);

const url = onboardUrl(mtLinkSdk.storedOptions, {
state,
redirectUri,
scopes,
email
});
state,
redirectUri,
scopes,
email
}
);

const query = qs.stringify({
const query = {
client_id: clientId,
response_type: 'code',
scope: scopes,
redirect_uri: redirectUri,
state,
country,
configs: generateConfigs({ email })
});
};

expect(url).toBe(`${MY_ACCOUNT_DOMAINS.production}/onboard?${query}`);
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/onboard', query})
});
});
});
23 changes: 12 additions & 11 deletions src/api/__tests__/onboard.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import qs from 'qs';
import { mocked } from 'ts-jest/utils';

import { MY_ACCOUNT_DOMAINS } from '../../server-paths';
import { MtLinkSdk } from '../..';
import onboard from '../onboard';
import { generateConfigs } from '../../helper';
import storage from '../../storage';
import expectUrlToMatchWithPKCE from '../../__tests__/helper/expect-url-to-match';

jest.mock('../../storage');

Expand Down Expand Up @@ -57,8 +57,9 @@ describe('api', () => {
onboard(mtLinkSdk.storedOptions);

expect(open).toBeCalledTimes(1);

const query = qs.stringify({
expect(open).toBeCalledWith(expect.any(String), '_self', 'noreferrer');
const url = open.mock.calls[0][0]
const query = {
client_id: clientId,
cobrand_client_id: cobrandClientId,
response_type: 'code',
Expand All @@ -67,9 +68,8 @@ describe('api', () => {
country,
locale,
configs: generateConfigs({ email })
});
const url = `${MY_ACCOUNT_DOMAINS.production}/onboard?${query}`;
expect(open).toBeCalledWith(url, '_self', 'noreferrer');
};
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/onboard', query})
});

test('with options', () => {
Expand All @@ -91,18 +91,19 @@ describe('api', () => {
});

expect(open).toBeCalledTimes(1);

const query = qs.stringify({
expect(open).toBeCalledWith(expect.any(String), '_self', 'noreferrer');
const url = open.mock.calls[0][0]
const query = {
client_id: clientId,
response_type: 'code',
scope: scopes,
redirect_uri: redirectUri,
state,
country,
configs: generateConfigs({ email })
});
const url = `${MY_ACCOUNT_DOMAINS.production}/onboard?${query}`;
expect(open).toBeCalledWith(url, '_self', 'noreferrer');
};

expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/onboard', query})
});

test('without window', () => {
Expand Down
11 changes: 2 additions & 9 deletions src/api/authorize-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@ export default function authorize(storedOptions: StoredOptions, options: Authori
throw new Error('[mt-link-sdk] Make sure to call `init` before calling `authorizeUrl/authorize`.');
}

const {
scopes = defaultScopes,
redirectUri = defaultRedirectUri,
pkce = false,
codeChallenge,
state,
...rest
} = options;
const { scopes = defaultScopes, redirectUri = defaultRedirectUri, codeChallenge, state, ...rest } = options;

if (!redirectUri) {
throw new Error(
Expand All @@ -37,7 +30,7 @@ export default function authorize(storedOptions: StoredOptions, options: Authori

storage.del('cv');

const cc = codeChallenge || (pkce && generateCodeChallenge());
const cc = codeChallenge || generateCodeChallenge();

const queryString = stringify({
client_id: clientId,
Expand Down
11 changes: 2 additions & 9 deletions src/api/onboard-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,7 @@ export default function onboardUrl(storedOptions: StoredOptions, options: Onboar
throw new Error('[mt-link-sdk] Make sure to call `init` before calling `onboardUrl/onboard`.');
}

const {
scopes = defaultScopes,
redirectUri = defaultRedirectUri,
pkce = false,
codeChallenge,
state,
...rest
} = options;
const { scopes = defaultScopes, redirectUri = defaultRedirectUri, codeChallenge, state, ...rest } = options;

const configs = mergeConfigs(storedOptions, rest, ['authAction', 'showAuthToggle', 'showRememberMe', 'forceLogout']);

Expand All @@ -38,7 +31,7 @@ export default function onboardUrl(storedOptions: StoredOptions, options: Onboar

storage.del('cv');

const cc = codeChallenge || (pkce && generateCodeChallenge());
const cc = codeChallenge || generateCodeChallenge();

const queryString = stringify({
client_id: clientId,
Expand Down
Loading

0 comments on commit 2234e0e

Please sign in to comment.