Skip to content

Commit 763994f

Browse files
committed
feat(javascript): add getRedirectBasedSignUpUrl utility and corresponding tests; update TypeScript configuration
1 parent 87e4501 commit 763994f

File tree

5 files changed

+148
-2
lines changed

5 files changed

+148
-2
lines changed

packages/javascript/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"typecheck": "tsc -p tsconfig.lib.json"
4343
},
4444
"devDependencies": {
45-
"@types/node": "^22.15.3",
45+
"@types/node": "^22.15.30",
4646
"@wso2/eslint-plugin": "catalog:",
4747
"@wso2/prettier-config": "catalog:",
4848
"esbuild": "^0.25.9",

packages/javascript/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ export {default as flattenUserSchema} from './utils/flattenUserSchema';
143143
export {default as generateUserProfile} from './utils/generateUserProfile';
144144
export {default as getLatestStateParam} from './utils/getLatestStateParam';
145145
export {default as generateFlattenedUserProfile} from './utils/generateFlattenedUserProfile';
146+
export {default as getRedirectBasedSignUpUrl} from './utils/getRedirectBasedSignUpUrl';
146147
export {default as getI18nBundles} from './utils/getI18nBundles';
147148
export {default as identifyPlatform} from './utils/identifyPlatform';
148149
export {default as isEmpty} from './utils/isEmpty';
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com).
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
import {describe, it, expect, vi, afterEach} from 'vitest';
20+
import {Config} from '../../models/config';
21+
import isRecognizedBaseUrlPattern from '../isRecognizedBaseUrlPattern';
22+
import getRedirectBasedSignUpUrl from '../getRedirectBasedSignUpUrl';
23+
24+
vi.mock('../isRecognizedBaseUrlPattern', () => ({default: vi.fn()}));
25+
26+
describe('getRedirectBasedSignUpUrl', () => {
27+
const baseUrl: string = 'https://api.asgardeo.io/t/org';
28+
const expectedBaseUrl: string = 'https://accounts.asgardeo.io/t/org';
29+
const clientId: string = 'client123';
30+
const applicationId: string = 'app456';
31+
32+
afterEach(() => {
33+
vi.clearAllMocks();
34+
});
35+
36+
it('returns the correct sign-up URL if baseUrl is recognized and both params are present', () => {
37+
(isRecognizedBaseUrlPattern as unknown as ReturnType<typeof vi.fn>).mockReturnValue(true);
38+
const config: Config = {baseUrl, clientId, applicationId};
39+
const url: URL = new URL(expectedBaseUrl + '/accountrecoveryendpoint/register.do');
40+
url.searchParams.set('client_id', clientId);
41+
url.searchParams.set('spId', applicationId);
42+
expect(getRedirectBasedSignUpUrl(config)).toBe(url.toString());
43+
});
44+
45+
it('returns the correct sign-up URL if only clientId is present', () => {
46+
(isRecognizedBaseUrlPattern as unknown as ReturnType<typeof vi.fn>).mockReturnValue(true);
47+
const config: Config = {baseUrl, clientId};
48+
const url: URL = new URL(expectedBaseUrl + '/accountrecoveryendpoint/register.do');
49+
url.searchParams.set('client_id', clientId);
50+
expect(getRedirectBasedSignUpUrl(config)).toBe(url.toString());
51+
});
52+
53+
it('returns the correct sign-up URL if only applicationId is present', () => {
54+
(isRecognizedBaseUrlPattern as unknown as ReturnType<typeof vi.fn>).mockReturnValue(true);
55+
const config: Config = {baseUrl, applicationId, clientId: ''};
56+
const url: URL = new URL(expectedBaseUrl + '/accountrecoveryendpoint/register.do');
57+
url.searchParams.set('spId', applicationId);
58+
expect(getRedirectBasedSignUpUrl(config)).toBe(url.toString());
59+
});
60+
61+
it('returns the correct sign-up URL if neither param is present', () => {
62+
(isRecognizedBaseUrlPattern as unknown as ReturnType<typeof vi.fn>).mockReturnValue(true);
63+
const config: Config = {baseUrl, clientId: ''};
64+
const url: URL = new URL(expectedBaseUrl + '/accountrecoveryendpoint/register.do');
65+
expect(getRedirectBasedSignUpUrl(config)).toBe(url.toString());
66+
});
67+
68+
it('returns empty string if baseUrl is not recognized', () => {
69+
(isRecognizedBaseUrlPattern as unknown as ReturnType<typeof vi.fn>).mockReturnValue(false);
70+
const config: Config = {baseUrl, clientId, applicationId};
71+
expect(getRedirectBasedSignUpUrl(config)).toBe('');
72+
});
73+
});
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/**
2+
* Copyright (c) 2025, WSO2 LLC. (https://www.wso2.com). All Rights Reserved.
3+
*
4+
* WSO2 LLC. licenses this file to you under the Apache License,
5+
* Version 2.0 (the "License"); you may not use this file except
6+
* in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing,
12+
* software distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
* KIND, either express or implied. See the License for the
15+
* specific language governing permissions and limitations
16+
* under the License.
17+
*/
18+
19+
import {Config} from '../models/config';
20+
import isRecognizedBaseUrlPattern from './isRecognizedBaseUrlPattern';
21+
import identifyPlatform from './identifyPlatform';
22+
import {Platform} from '../models/platforms';
23+
import logger from './logger';
24+
25+
/**
26+
* Utility to generate the redirect-based sign-up URL for Asgardeo.
27+
*
28+
* If the baseUrl is recognized (standard Asgardeo pattern), constructs the sign-up URL.
29+
* Otherwise, returns an empty string.
30+
*
31+
* @param baseUrl - The base URL of the Asgardeo identity server (string or undefined)
32+
* @returns The sign-up URL if baseUrl is recognized, otherwise an empty string
33+
*/
34+
const getRedirectBasedSignUpUrl = (config: Config): string => {
35+
const {baseUrl} = config;
36+
37+
if (!isRecognizedBaseUrlPattern(baseUrl)) return '';
38+
39+
let signUpBaseUrl: string = baseUrl;
40+
41+
if (identifyPlatform(config) === Platform.Asgardeo) {
42+
try {
43+
const url: URL = new URL(baseUrl!);
44+
45+
// Replace 'api.' with 'accounts.' in the hostname, preserving subdomains like 'dev.'
46+
if (/([a-z0-9-]+\.)*api\.asgardeo\.io$/i.test(url.hostname)) {
47+
url.hostname = url.hostname.replace('api.', 'accounts.');
48+
signUpBaseUrl = url.toString().replace(/\/$/, ''); // Remove trailing slash if any
49+
}
50+
} catch {
51+
logger.debug(
52+
`[getRedirectBasedSignUpUrl] Could not parse base URL to replace 'api.' with 'accounts.'. Base URL: ${baseUrl}`,
53+
);
54+
}
55+
}
56+
57+
const url: URL = new URL(signUpBaseUrl + '/accountrecoveryendpoint/register.do');
58+
59+
if (config.clientId) {
60+
url.searchParams.set('client_id', config.clientId);
61+
}
62+
63+
if (config.applicationId) {
64+
url.searchParams.set('spId', config.applicationId);
65+
}
66+
67+
logger.debug(`[getRedirectBasedSignUpUrl] Generated sign-up URL: ${url.toString()}`);
68+
69+
return url.toString();
70+
};
71+
72+
export default getRedirectBasedSignUpUrl;

packages/javascript/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"esModuleInterop": true,
77
"experimentalDecorators": true,
88
"importHelpers": true,
9-
"lib": ["ESNext"],
9+
"lib": ["ESNext", "DOM"],
1010
"module": "ESNext",
1111
"moduleResolution": "node",
1212
"skipLibCheck": true,

0 commit comments

Comments
 (0)