From 89e9f9eecf959470bc88b5d3b8fb9b4f4edebd68 Mon Sep 17 00:00:00 2001 From: CeciliaAvila Date: Thu, 7 Dec 2023 13:22:11 -0300 Subject: [PATCH 1/3] Provide proxy setting to openIdMetadata --- libraries/botframework-connector/package.json | 2 ++ .../src/auth/jwtTokenExtractor.ts | 15 +++++++++++---- .../src/auth/openIdMetadata.ts | 14 +++++++++++--- .../parameterizedBotFrameworkAuthentication.ts | 9 ++++++--- yarn.lock | 15 +++++++++++++++ 5 files changed, 45 insertions(+), 10 deletions(-) diff --git a/libraries/botframework-connector/package.json b/libraries/botframework-connector/package.json index 5ca4e70ea1..95580c9fa7 100644 --- a/libraries/botframework-connector/package.json +++ b/libraries/botframework-connector/package.json @@ -35,7 +35,9 @@ "botbuilder-stdlib": "4.1.6", "botframework-schema": "4.1.6", "cross-fetch": "^3.0.5", + "https-proxy-agent": "^7.0.2", "jsonwebtoken": "^9.0.0", + "node-fetch": "^2.6.7", "rsa-pem-from-mod-exp": "^0.8.4", "zod": "^3.22.4" }, diff --git a/libraries/botframework-connector/src/auth/jwtTokenExtractor.ts b/libraries/botframework-connector/src/auth/jwtTokenExtractor.ts index fd2f1f71bf..c1937d2541 100644 --- a/libraries/botframework-connector/src/auth/jwtTokenExtractor.ts +++ b/libraries/botframework-connector/src/auth/jwtTokenExtractor.ts @@ -12,6 +12,7 @@ import { EndorsementsValidator } from './endorsementsValidator'; import { OpenIdMetadata } from './openIdMetadata'; import { AuthenticationError } from './authenticationError'; import { StatusCodes } from 'botframework-schema'; +import { ProxySettings } from '@azure/ms-rest-js'; /** * A JWT token processing class that gets identity information and performs security token validation. @@ -32,17 +33,23 @@ export class JwtTokenExtractor { * @param tokenValidationParameters Token validation parameters. * @param metadataUrl Metadata Url. * @param allowedSigningAlgorithms Allowed signing algorithms. + * @param proxySettings The proxy settings for the request. */ - constructor(tokenValidationParameters: VerifyOptions, metadataUrl: string, allowedSigningAlgorithms: string[]) { + constructor( + tokenValidationParameters: VerifyOptions, + metadataUrl: string, + allowedSigningAlgorithms: string[], + proxySettings?: ProxySettings + ) { this.tokenValidationParameters = { ...tokenValidationParameters }; this.tokenValidationParameters.algorithms = allowedSigningAlgorithms; - this.openIdMetadata = JwtTokenExtractor.getOrAddOpenIdMetadata(metadataUrl); + this.openIdMetadata = JwtTokenExtractor.getOrAddOpenIdMetadata(metadataUrl, proxySettings); } - private static getOrAddOpenIdMetadata(metadataUrl: string): OpenIdMetadata { + private static getOrAddOpenIdMetadata(metadataUrl: string, proxySettings?: ProxySettings): OpenIdMetadata { let metadata = this.openIdMetadataCache.get(metadataUrl); if (!metadata) { - metadata = new OpenIdMetadata(metadataUrl); + metadata = new OpenIdMetadata(metadataUrl, proxySettings); this.openIdMetadataCache.set(metadataUrl, metadata); } diff --git a/libraries/botframework-connector/src/auth/openIdMetadata.ts b/libraries/botframework-connector/src/auth/openIdMetadata.ts index c084d30037..a06b1292a4 100644 --- a/libraries/botframework-connector/src/auth/openIdMetadata.ts +++ b/libraries/botframework-connector/src/auth/openIdMetadata.ts @@ -8,9 +8,11 @@ import * as getPem from 'rsa-pem-from-mod-exp'; import base64url from 'base64url'; -import fetch from 'cross-fetch'; +import fetch from 'node-fetch'; +import { HttpsProxyAgent } from 'https-proxy-agent'; import { AuthenticationError } from './authenticationError'; import { StatusCodes } from 'botframework-schema'; +import { ProxySettings } from '@azure/ms-rest-js'; /** * Class in charge of manage OpenId metadata. @@ -23,8 +25,9 @@ export class OpenIdMetadata { * Initializes a new instance of the [OpenIdMetadata](xref:botframework-connector.OpenIdMetadata) class. * * @param url Metadata Url. + * @param proxySettings The proxy settings for the request. */ - constructor(private url: string) {} + constructor(private url: string, private proxySettings?: ProxySettings) {} /** * Gets the Signing key. @@ -56,7 +59,12 @@ export class OpenIdMetadata { * @private */ private async refreshCache(): Promise { - const res = await fetch(this.url); + let agent = null; + if (this.proxySettings) { + const proxyUrl = `http://${this.proxySettings.host}:${this.proxySettings.port}`; + agent = new HttpsProxyAgent(proxyUrl); + } + const res = await fetch(this.url, { agent: agent }); if (res.ok) { const openIdConfig = (await res.json()) as IOpenIdConfig; diff --git a/libraries/botframework-connector/src/auth/parameterizedBotFrameworkAuthentication.ts b/libraries/botframework-connector/src/auth/parameterizedBotFrameworkAuthentication.ts index d6e8f20dd9..acfb654836 100644 --- a/libraries/botframework-connector/src/auth/parameterizedBotFrameworkAuthentication.ts +++ b/libraries/botframework-connector/src/auth/parameterizedBotFrameworkAuthentication.ts @@ -298,7 +298,8 @@ export class ParameterizedBotFrameworkAuthentication extends BotFrameworkAuthent const tokenExtractor = new JwtTokenExtractor( verifyOptions, this.toBotFromEmulatorOpenIdMetadataUrl, - AuthenticationConstants.AllowedSigningAlgorithms + AuthenticationConstants.AllowedSigningAlgorithms, + this.connectorClientOptions?.proxySettings ); const parts: string[] = authHeader.split(' '); @@ -384,7 +385,8 @@ export class ParameterizedBotFrameworkAuthentication extends BotFrameworkAuthent const tokenExtractor: JwtTokenExtractor = new JwtTokenExtractor( verifyOptions, this.toBotFromEmulatorOpenIdMetadataUrl, - AuthenticationConstants.AllowedSigningAlgorithms + AuthenticationConstants.AllowedSigningAlgorithms, + this.connectorClientOptions?.proxySettings ); const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader( @@ -470,7 +472,8 @@ export class ParameterizedBotFrameworkAuthentication extends BotFrameworkAuthent const tokenExtractor: JwtTokenExtractor = new JwtTokenExtractor( tokenValidationParameters, this.toBotFromChannelOpenIdMetadataUrl, - AuthenticationConstants.AllowedSigningAlgorithms + AuthenticationConstants.AllowedSigningAlgorithms, + this.connectorClientOptions?.proxySettings ); const identity: ClaimsIdentity = await tokenExtractor.getIdentityFromAuthHeader( diff --git a/yarn.lock b/yarn.lock index e7a453183e..5adfa7000d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2838,6 +2838,13 @@ agent-base@6: dependencies: debug "4" +agent-base@^7.0.2: + version "7.1.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.0.tgz#536802b76bc0b34aa50195eb2442276d613e3434" + integrity sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg== + dependencies: + debug "^4.3.4" + agentkeepalive@^4.1.3: version "4.1.4" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.1.4.tgz#d928028a4862cb11718e55227872e842a44c945b" @@ -7528,6 +7535,14 @@ https-proxy-agent@5.0.0, https-proxy-agent@^5.0.0: agent-base "6" debug "4" +https-proxy-agent@^7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz#e2645b846b90e96c6e6f347fb5b2e41f1590b09b" + integrity sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA== + dependencies: + agent-base "^7.0.2" + debug "4" + humanize-ms@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" From 3ef8e089114475bca7aa11d8a9ebfad63731f956 Mon Sep 17 00:00:00 2001 From: CeciliaAvila Date: Tue, 12 Dec 2023 09:52:47 -0300 Subject: [PATCH 2/3] Replace @azure/ms-rest-js with @azure/core-http --- libraries/botframework-connector/src/auth/jwtTokenExtractor.ts | 2 +- libraries/botframework-connector/src/auth/openIdMetadata.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/botframework-connector/src/auth/jwtTokenExtractor.ts b/libraries/botframework-connector/src/auth/jwtTokenExtractor.ts index c1937d2541..7f713cf9af 100644 --- a/libraries/botframework-connector/src/auth/jwtTokenExtractor.ts +++ b/libraries/botframework-connector/src/auth/jwtTokenExtractor.ts @@ -12,7 +12,7 @@ import { EndorsementsValidator } from './endorsementsValidator'; import { OpenIdMetadata } from './openIdMetadata'; import { AuthenticationError } from './authenticationError'; import { StatusCodes } from 'botframework-schema'; -import { ProxySettings } from '@azure/ms-rest-js'; +import { ProxySettings } from '@azure/core-http'; /** * A JWT token processing class that gets identity information and performs security token validation. diff --git a/libraries/botframework-connector/src/auth/openIdMetadata.ts b/libraries/botframework-connector/src/auth/openIdMetadata.ts index a06b1292a4..1c98126cd2 100644 --- a/libraries/botframework-connector/src/auth/openIdMetadata.ts +++ b/libraries/botframework-connector/src/auth/openIdMetadata.ts @@ -12,7 +12,7 @@ import fetch from 'node-fetch'; import { HttpsProxyAgent } from 'https-proxy-agent'; import { AuthenticationError } from './authenticationError'; import { StatusCodes } from 'botframework-schema'; -import { ProxySettings } from '@azure/ms-rest-js'; +import { ProxySettings } from '@azure/core-http'; /** * Class in charge of manage OpenId metadata. From 0abb7bc21bbeae09f419582515c076c316715b71 Mon Sep 17 00:00:00 2001 From: CeciliaAvila Date: Mon, 18 Dec 2023 16:07:30 -0300 Subject: [PATCH 3/3] Add missing agent settings in getKeys call --- libraries/botframework-connector/src/auth/openIdMetadata.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/botframework-connector/src/auth/openIdMetadata.ts b/libraries/botframework-connector/src/auth/openIdMetadata.ts index 1c98126cd2..49d5ae9f01 100644 --- a/libraries/botframework-connector/src/auth/openIdMetadata.ts +++ b/libraries/botframework-connector/src/auth/openIdMetadata.ts @@ -69,7 +69,7 @@ export class OpenIdMetadata { if (res.ok) { const openIdConfig = (await res.json()) as IOpenIdConfig; - const getKeyResponse = await fetch(openIdConfig.jwks_uri); + const getKeyResponse = await fetch(openIdConfig.jwks_uri, { agent: agent }); if (getKeyResponse.ok) { this.lastUpdated = new Date().getTime(); this.keys = (await getKeyResponse.json()).keys as IKey[];