Skip to content

Commit b92acf7

Browse files
committed
refuse unacceptable values for AuthnMethod and AuthAction
1 parent 29bf6a9 commit b92acf7

File tree

3 files changed

+86
-4
lines changed

3 files changed

+86
-4
lines changed

src/__tests__/helper.test.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { constructScopes, getIsTabValue, mergeConfigs, generateConfigs } from '../helper';
22
import packageJson from '../../package.json';
3-
import { ConfigsOptions } from '../typings';
3+
import { AuthAction, AuthnMethod, ConfigsOptions } from '../typings';
44
import { stringify } from 'qs';
55

66
describe('helper', () => {
@@ -158,6 +158,38 @@ describe('helper', () => {
158158
);
159159
});
160160

161+
test('Should filter out invalid authnMethod from array and authAction values', () => {
162+
const configPayload: ConfigsOptions = {
163+
email: 'email',
164+
backTo: 'backTo',
165+
authAction: 'invalid-value' as AuthAction,
166+
showAuthToggle: true,
167+
showRememberMe: true,
168+
authnMethod: ['oh-not-valid', 'sso'] as AuthnMethod[]
169+
};
170+
171+
expect(generateConfigs(configPayload)).toBe(
172+
`sdk_platform=js&sdk_version=${packageJson.version}&email=email&back_to=backTo&show_auth_toggle=true` +
173+
`&show_remember_me=true&authn_method=sso`
174+
);
175+
});
176+
177+
test('Should reject invalid authnMethod from config', () => {
178+
const configPayload: ConfigsOptions = {
179+
email: 'email',
180+
backTo: 'backTo',
181+
authAction: 'signup',
182+
showAuthToggle: true,
183+
showRememberMe: true,
184+
authnMethod: 'oh-not-valid' as AuthnMethod
185+
};
186+
187+
expect(generateConfigs(configPayload)).toBe(
188+
`sdk_platform=js&sdk_version=${packageJson.version}&email=email&back_to=backTo&auth_action=signup&show_auth_toggle=true` +
189+
`&show_remember_me=true`
190+
);
191+
});
192+
161193
test('without parameter', () => {
162194
expect(generateConfigs()).toBe(`sdk_platform=js&sdk_version=${packageJson.version}`);
163195
});

src/helper.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@ import { encode } from 'url-safe-base64';
77
import { v4 as uuid } from 'uuid';
88
import storage from './storage';
99

10-
import { Scopes, InitOptions, ConfigsOptions, AuthAction, AuthnMethod } from './typings';
10+
import {
11+
Scopes,
12+
InitOptions,
13+
ConfigsOptions,
14+
AuthAction,
15+
AuthnMethod,
16+
supportedAuthnMethod,
17+
supportedAuthAction
18+
} from './typings';
1119

1220
export function constructScopes(scopes: Scopes = ''): string | undefined {
1321
return (Array.isArray(scopes) ? scopes.join(' ') : scopes) || undefined;
@@ -79,6 +87,14 @@ export function generateConfigs(configs: ConfigsOptions = {}): string {
7987
'authnMethod'
8088
];
8189

90+
if (configs.authnMethod) {
91+
configs.authnMethod = parseAuthnMethod(configs.authnMethod);
92+
}
93+
94+
if (configs.authAction) {
95+
configs.authAction = parseAuthAction(configs.authAction);
96+
}
97+
8298
for (const key in configs) {
8399
if (configKeys.indexOf(key) !== -1) {
84100
snakeCaseConfigs[snakeCase(key)] = configs[key as keyof ConfigsOptions];
@@ -95,6 +111,37 @@ export function generateConfigs(configs: ConfigsOptions = {}): string {
95111
);
96112
}
97113

114+
function isAuthnMethod(x: unknown): x is AuthnMethod | AuthnMethod[] {
115+
if (Array.isArray(x)) {
116+
return (
117+
x.length > 0 &&
118+
x.every((el: AuthnMethod) => {
119+
return supportedAuthnMethod.includes(el);
120+
})
121+
);
122+
}
123+
124+
return supportedAuthnMethod.includes(x as AuthnMethod);
125+
}
126+
127+
function parseAuthnMethod(x: unknown): AuthnMethod[] | AuthnMethod | undefined {
128+
if (Array.isArray(x)) {
129+
let filtered_x = x.filter((el: AuthnMethod) => supportedAuthnMethod.includes(el));
130+
131+
filtered_x.length == 1 ? (x = filtered_x.toString()) : (x = filtered_x);
132+
}
133+
134+
return isAuthnMethod(x) ? x : undefined;
135+
}
136+
137+
function isAuthAction(x: unknown): x is AuthAction {
138+
return supportedAuthAction.includes(x as AuthAction);
139+
}
140+
141+
function parseAuthAction(x: unknown): AuthAction | undefined {
142+
return isAuthAction(x) ? x : undefined;
143+
}
144+
98145
export function generateCodeChallenge(): string {
99146
const codeVerifier = uuid();
100147

src/typings.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
export type AuthAction = 'login' | 'signup';
1+
export const supportedAuthAction = ['login', 'signup'] as const;
2+
export type AuthAction = typeof supportedAuthAction[number];
23

34
export interface PrivateParams {
45
cobrandClientId?: string;
@@ -10,7 +11,9 @@ export interface PrivateConfigsOptions {
1011
sdkVersion?: string; // semver
1112
}
1213

13-
export type AuthnMethod = 'passwordless' | 'sso' | 'credentials';
14+
export const supportedAuthnMethod = ['passwordless', 'sso', 'credentials'] as const;
15+
export type AuthnMethod = typeof supportedAuthnMethod[number];
16+
1417
export interface ConfigsOptions extends PrivateConfigsOptions {
1518
email?: string;
1619
backTo?: string;

0 commit comments

Comments
 (0)