From 3310aefdb573eaa19ac4ddd363195a7768fa4b81 Mon Sep 17 00:00:00 2001 From: Hassan_Wari Date: Tue, 13 Aug 2024 15:12:07 +0300 Subject: [PATCH 1/2] fix(url): handle special characters in connection params --- packages/shared/lib/clients/oauth2.client.ts | 9 ++++--- packages/shared/lib/utils/utils.ts | 4 ++++ packages/shared/lib/utils/utils.unit.test.ts | 25 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/packages/shared/lib/clients/oauth2.client.ts b/packages/shared/lib/clients/oauth2.client.ts index f0d99113d1..0a1192892d 100644 --- a/packages/shared/lib/clients/oauth2.client.ts +++ b/packages/shared/lib/clients/oauth2.client.ts @@ -5,7 +5,7 @@ import { AuthorizationCode } from 'simple-oauth2'; import connectionsManager from '../services/connection.service.js'; import type { ServiceResponse } from '../models/Generic.js'; import { LogActionEnum } from '../models/Telemetry.js'; -import { interpolateString } from '../utils/utils.js'; +import { interpolateString, encodeParameters } from '../utils/utils.js'; import Boom from '@hapi/boom'; import { NangoError } from '../utils/error.js'; import errorManager, { ErrorSourceEnum } from '../utils/error.manager.js'; @@ -18,10 +18,9 @@ export function getSimpleOAuth2ClientConfig( connectionConfig: Record ): Merge { const templateTokenUrl = typeof template.token_url === 'string' ? template.token_url : (template.token_url!['OAUTH2'] as string); - const strippedTokenUrl = templateTokenUrl.replace(/connectionConfig\./g, ''); - const tokenUrl = new URL(interpolateString(strippedTokenUrl, connectionConfig)); - const strippedAuthorizeUrl = template.authorization_url!.replace(/connectionConfig\./g, ''); - const authorizeUrl = new URL(interpolateString(strippedAuthorizeUrl, connectionConfig)); + const tokenUrl = new URL(interpolateString(templateTokenUrl.replace(/connectionConfig\./g, ''), encodeParameters(connectionConfig))); + const authorizeUrl = new URL(interpolateString(template.authorization_url!.replace(/connectionConfig\./g, ''), encodeParameters(connectionConfig))); + const headers = { 'User-Agent': 'Nango' }; const authConfig = template as ProviderTemplateOAuth2; diff --git a/packages/shared/lib/utils/utils.ts b/packages/shared/lib/utils/utils.ts index 0b080a8e0f..8d17be4f07 100644 --- a/packages/shared/lib/utils/utils.ts +++ b/packages/shared/lib/utils/utils.ts @@ -239,3 +239,7 @@ export function getConnectionConfig(queryParams: any): Record { const arr = Object.entries(queryParams).filter(([, v]) => typeof v === 'string'); // Filter strings return Object.fromEntries(arr) as Record; } + +export function encodeParameters(params: Record): Record { + return Object.fromEntries(Object.entries(params).map(([key, value]) => [key, encodeURIComponent(String(value))])); +} diff --git a/packages/shared/lib/utils/utils.unit.test.ts b/packages/shared/lib/utils/utils.unit.test.ts index 0cab77594a..5cceb19230 100644 --- a/packages/shared/lib/utils/utils.unit.test.ts +++ b/packages/shared/lib/utils/utils.unit.test.ts @@ -12,3 +12,28 @@ describe('Proxy service Construct Header Tests', () => { expect(utils.isValidHttpUrl('/api/v2/tickets?per_page=100&include=requester,description&page=3')).toBe(false); }); }); +describe('encodeParameters Function Tests', () => { + it('should encode parameters correctly', () => { + const params = { + redirectUri: 'https://redirectme.com' + }; + + const expected = { + redirectUri: 'https%3A%2F%2Fredirectme.com' + }; + + expect(utils.encodeParameters(params)).toEqual(expected); + }); + + it('should handle parameters with special characters', () => { + const params = { + redirectUri: 'https://redirectme.com?param=value&another=value' + }; + + const expected = { + redirectUri: 'https%3A%2F%2Fredirectme.com%3Fparam%3Dvalue%26another%3Dvalue' + }; + + expect(utils.encodeParameters(params)).toEqual(expected); + }); +}); From e8a3f15685c3ca45de7014f2c9a62acf4445d24f Mon Sep 17 00:00:00 2001 From: Hassan_Wari Date: Wed, 14 Aug 2024 12:44:41 +0300 Subject: [PATCH 2/2] review --- packages/shared/lib/clients/oauth2.client.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/shared/lib/clients/oauth2.client.ts b/packages/shared/lib/clients/oauth2.client.ts index 0a1192892d..0743b58c4a 100644 --- a/packages/shared/lib/clients/oauth2.client.ts +++ b/packages/shared/lib/clients/oauth2.client.ts @@ -18,8 +18,8 @@ export function getSimpleOAuth2ClientConfig( connectionConfig: Record ): Merge { const templateTokenUrl = typeof template.token_url === 'string' ? template.token_url : (template.token_url!['OAUTH2'] as string); - const tokenUrl = new URL(interpolateString(templateTokenUrl.replace(/connectionConfig\./g, ''), encodeParameters(connectionConfig))); - const authorizeUrl = new URL(interpolateString(template.authorization_url!.replace(/connectionConfig\./g, ''), encodeParameters(connectionConfig))); + const tokenUrl = makeUrl(templateTokenUrl, connectionConfig); + const authorizeUrl = makeUrl(template.authorization_url!, connectionConfig); const headers = { 'User-Agent': 'Nango' }; @@ -156,3 +156,10 @@ export async function getFreshOAuth2Credentials( return { success: false, error, response: null }; } } + +function makeUrl(template: string, config: Record): URL { + const cleanTemplate = template.replace(/connectionConfig\./g, ''); + const encodedParams = encodeParameters(config); + const interpolatedUrl = interpolateString(cleanTemplate, encodedParams); + return new URL(interpolatedUrl); +}