diff --git a/libraries/botbuilder/src/botFrameworkHttpClient.ts b/libraries/botbuilder/src/botFrameworkHttpClient.ts index ab49b2a474..3201b05e4e 100644 --- a/libraries/botbuilder/src/botFrameworkHttpClient.ts +++ b/libraries/botbuilder/src/botFrameworkHttpClient.ts @@ -29,7 +29,7 @@ export class BotFrameworkHttpClient { */ private static readonly appCredentialMapCache: Map = new Map(); - constructor(private readonly credentialProvider: ICredentialProvider, private readonly channelService?: string) { + public constructor(private readonly credentialProvider: ICredentialProvider, private readonly channelService?: string) { if (!this.credentialProvider) { throw new Error('BotFrameworkHttpClient(): missing credentialProvider'); } @@ -96,6 +96,19 @@ export class BotFrameworkHttpClient { } } + protected async buildCredentials(appId: string, oAuthScope?: string): Promise { + const appPassword = await this.credentialProvider.getAppPassword(appId); + let appCredentials; + if (JwtTokenValidation.isGovernment(this.channelService)) { + appCredentials = new MicrosoftAppCredentials(appId, appPassword, this.channelService, oAuthScope); + appCredentials.oAuthEndpoint = GovernmentConstants.ToChannelFromBotLoginUrl; + appCredentials.oAuthScope = GovernmentConstants.ToChannelFromBotOAuthScope; + } else { + appCredentials = new MicrosoftAppCredentials(appId, appPassword, this.channelService, oAuthScope); + } + return appCredentials; + } + /** * Gets the application credentials. App Credentials are cached so as to ensure we are not refreshing * token every time. @@ -114,14 +127,8 @@ export class BotFrameworkHttpClient { return appCredentials; } - const appPassword = await this.credentialProvider.getAppPassword(appId); - if (JwtTokenValidation.isGovernment(this.channelService)) { - appCredentials = new MicrosoftAppCredentials(appId, appPassword, this.channelService, oAuthScope); - appCredentials.oAuthEndpoint = GovernmentConstants.ToChannelFromBotLoginUrl; - appCredentials.oAuthScope = GovernmentConstants.ToChannelFromBotOAuthScope; - } else { - appCredentials = new MicrosoftAppCredentials(appId, appPassword, this.channelService, oAuthScope); - } + // Credentials not found in cache, build them + appCredentials = await this.buildCredentials(appId, oAuthScope); // Cache the credentials for later use BotFrameworkHttpClient.appCredentialMapCache.set(cacheKey, appCredentials); diff --git a/libraries/botbuilder/tests/botFrameworkHttpClient.test.js b/libraries/botbuilder/tests/botFrameworkHttpClient.test.js index 19585bf309..1e394dcc9f 100644 --- a/libraries/botbuilder/tests/botFrameworkHttpClient.test.js +++ b/libraries/botbuilder/tests/botFrameworkHttpClient.test.js @@ -1,8 +1,17 @@ const { strictEqual } = require('assert'); const { BotFrameworkHttpClient } = require('../'); -const { AuthenticationConstants, SimpleCredentialProvider } = require('botframework-connector'); +const { AuthenticationConstants, SimpleCredentialProvider, MicrosoftAppCredentials } = require('botframework-connector'); const nock = require('nock'); +class TestBotFrameworkHttpClient extends BotFrameworkHttpClient { + constructor(credentialProvider, channelService) { + super(credentialProvider, channelService); + } + async buildCredentials() { + return new MicrosoftAppCredentials('', ''); + } +} + describe('BotFrameworkHttpClient', function() { this.timeout(3000); describe('constructor()', () => { @@ -56,5 +65,18 @@ describe('BotFrameworkHttpClient', function() { const response = await client.postActivity(fromBotId, 'toBotId', 'http://skillUrl/api/bad', 'serviceUrl', 'conversationId', { type: 'message', conversation: { } }); strictEqual(response.status, 404); }); + + it('should succeed to make call using override buildCredentials', async () => { + + nock('http://skillUrl') + .post('/api/good') + .reply(200, { id: 'some-id' }); + + const credentialProvider = new SimpleCredentialProvider('this-is-not-the-app-id-your-looking-for', '1'); + const client = new TestBotFrameworkHttpClient(credentialProvider, 'channels'); + const fromBotId = 'this-is-not-the-app-id-your-looking-for'; + const response = await client.postActivity(fromBotId, 'toBotId', 'http://skillUrl/api/good', 'serviceUrl', 'conversationId', { type: 'message', conversation: { } }); + strictEqual(response.status, 200); + }); }); });