Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions libraries/botbuilder/src/botFrameworkHttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class BotFrameworkHttpClient {
*/
private static readonly appCredentialMapCache: Map<string, MicrosoftAppCredentials> = new Map<string, MicrosoftAppCredentials>();

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');
}
Expand Down Expand Up @@ -96,6 +96,19 @@ export class BotFrameworkHttpClient {
}
}

protected async buildCredentials(appId: string, oAuthScope?: string): Promise<MicrosoftAppCredentials> {
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.
Expand All @@ -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);
Expand Down
24 changes: 23 additions & 1 deletion libraries/botbuilder/tests/botFrameworkHttpClient.test.js
Original file line number Diff line number Diff line change
@@ -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()', () => {
Expand Down Expand Up @@ -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);
});
});
});