Skip to content

Commit 016faac

Browse files
committed
refactor BFAdapter for Skills with Auth
1 parent fe85099 commit 016faac

File tree

4 files changed

+158
-60
lines changed

4 files changed

+158
-60
lines changed

libraries/botbuilder/src/botFrameworkAdapter.ts

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -247,8 +247,12 @@ export const INVOKE_RESPONSE_KEY: symbol = Symbol('invokeResponse');
247247
* ```
248248
*/
249249
export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvider, RequestHandler {
250-
public static readonly BotIdentityKey: string = 'BotIdentity';
251-
public static readonly ConnectorClientKey: string = 'ConnectorClient';
250+
// These keys are public to permit access to the keys from the adapter when it's a being
251+
// from library that does not have access to static properties off of BotFrameworkAdapter.
252+
// E.g. botbuilder-dialogs
253+
public readonly BotIdentityKey: Symbol = Symbol('BotIdentity');
254+
public readonly ConnectorClientKey: Symbol = Symbol('ConnectorClient');
255+
252256
protected readonly credentials: AppCredentials;
253257
protected readonly credentialsProvider: SimpleCredentialProvider;
254258
protected readonly settings: BotFrameworkAdapterSettings;
@@ -489,7 +493,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
489493
throw new Error(`BotFrameworkAdapter.deleteActivity(): missing conversation or conversation.id`);
490494
}
491495
if (!reference.activityId) { throw new Error(`BotFrameworkAdapter.deleteActivity(): missing activityId`); }
492-
const client: ConnectorClient = this.createConnectorClient(reference.serviceUrl);
496+
const client: ConnectorClient = this.getOrCreateConnectorClient(context, reference.serviceUrl, this.credentials);
493497
await client.conversations.deleteActivity(reference.conversation.id, reference.activityId);
494498
}
495499

@@ -511,7 +515,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
511515
}
512516
const serviceUrl: string = context.activity.serviceUrl;
513517
const conversationId: string = context.activity.conversation.id;
514-
const client: ConnectorClient = this.createConnectorClient(serviceUrl);
518+
const client: ConnectorClient = this.getOrCreateConnectorClient(context, serviceUrl, this.credentials);
515519
await client.conversations.deleteConversationMember(conversationId, memberId);
516520
}
517521

@@ -542,7 +546,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
542546
}
543547
const serviceUrl: string = context.activity.serviceUrl;
544548
const conversationId: string = context.activity.conversation.id;
545-
const client: ConnectorClient = this.createConnectorClient(serviceUrl);
549+
const client: ConnectorClient = this.getOrCreateConnectorClient(context, serviceUrl, this.credentials);
546550

547551
return await client.conversations.getActivityMembers(conversationId, activityId);
548552
}
@@ -569,7 +573,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
569573
}
570574
const serviceUrl: string = context.activity.serviceUrl;
571575
const conversationId: string = context.activity.conversation.id;
572-
const client: ConnectorClient = this.createConnectorClient(serviceUrl);
576+
const client: ConnectorClient = this.getOrCreateConnectorClient(context, serviceUrl, this.credentials);
573577

574578
return await client.conversations.getConversationMembers(conversationId);
575579
}
@@ -599,8 +603,13 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
599603
* `contextOrServiceUrl`.[activity](xref:botbuilder-core.TurnContext.activity).[serviceUrl](xref:botframework-schema.Activity.serviceUrl).
600604
*/
601605
public async getConversations(contextOrServiceUrl: TurnContext | string, continuationToken?: string): Promise<ConversationsResult> {
602-
const url: string = typeof contextOrServiceUrl === 'object' ? contextOrServiceUrl.activity.serviceUrl : contextOrServiceUrl;
603-
const client: ConnectorClient = this.createConnectorClient(url);
606+
let client: ConnectorClient;
607+
if (typeof contextOrServiceUrl === 'object') {
608+
const context: TurnContext = contextOrServiceUrl as TurnContext;
609+
client = this.getOrCreateConnectorClient(context, context.activity.serviceUrl, this.credentials);
610+
} else {
611+
client = this.createConnectorClient(contextOrServiceUrl as string);
612+
}
604613

605614
return await client.conversations.getConversations(continuationToken ? { continuationToken: continuationToken } : undefined);
606615
}
@@ -803,16 +812,16 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
803812
// Authenticate the incoming request
804813
status = 401;
805814
const authHeader: string = req.headers.authorization || req.headers.Authorization || '';
806-
await this.authenticateRequest(request, authHeader);
807815

808816
const identity = await this.authenticateRequestInternal(request, authHeader);
809817

810818
// Process received activity
811819
status = 500;
812820
const context: TurnContext = this.createContext(request);
813-
context.turnState.set(BotFrameworkAdapter.BotIdentityKey, identity);
821+
context.turnState.set(this.BotIdentityKey, identity);
814822
const connectorClient = await this.createConnectorClientWithIdentity(request.serviceUrl, identity);
815-
context.turnState.set(BotFrameworkAdapter.ConnectorClientKey, connectorClient);
823+
context.turnState.set(this.ConnectorClientKey, connectorClient);
824+
816825
context.turnState.set(BotCallbackHandlerKey, logic);
817826
await this.runMiddleware(context, logic);
818827

@@ -935,7 +944,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
935944
if (activity && BotFrameworkAdapter.isStreamingServiceUrl(activity.serviceUrl)) {
936945
TokenResolver.checkForOAuthCards(this, context, activity as Activity);
937946
}
938-
const client: ConnectorClient = this.createConnectorClient(activity.serviceUrl);
947+
const client = this.getOrCreateConnectorClient(context, activity.serviceUrl, this.credentials);
939948
if (activity.type === 'trace' && activity.channelId !== 'emulator') {
940949
// Just eat activity
941950
responses.push({} as ResourceResponse);
@@ -976,7 +985,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
976985
throw new Error(`BotFrameworkAdapter.updateActivity(): missing conversation or conversation.id`);
977986
}
978987
if (!activity.id) { throw new Error(`BotFrameworkAdapter.updateActivity(): missing activity.id`); }
979-
const client: ConnectorClient = this.createConnectorClient(activity.serviceUrl);
988+
const client: ConnectorClient = this.getOrCreateConnectorClient(context, activity.serviceUrl, this.credentials);
980989
await client.conversations.updateActivity(
981990
activity.conversation.id,
982991
activity.id,
@@ -1063,6 +1072,26 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
10631072
return new ConnectorClient(credentials, { baseUri: serviceUrl, userAgent: USER_AGENT });
10641073
}
10651074

1075+
/**
1076+
* @private
1077+
* Retrieves the ConnectorClient from the TurnContext or creates a new ConnectorClient with the provided serviceUrl and credentials.
1078+
* @param context
1079+
* @param serviceUrl
1080+
* @param credentials
1081+
*/
1082+
private getOrCreateConnectorClient(context: TurnContext, serviceUrl: string, credentials: AppCredentials): ConnectorClient {
1083+
if (!context || !context.turnState) throw new Error('invalid context parameter');
1084+
if (!serviceUrl) throw new Error('invalid serviceUrl');
1085+
if (!credentials) throw new Error('invalid credentials');
1086+
1087+
let client: ConnectorClient = context.turnState.get(this.ConnectorClientKey);
1088+
if (!client) {
1089+
client = this.createConnectorClientInternal(serviceUrl, credentials);
1090+
}
1091+
1092+
return client;
1093+
}
1094+
10661095
/**
10671096
*
10681097
* @remarks
@@ -1073,7 +1102,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide
10731102
// There is no cache for AppCredentials in JS as opposed to C#.
10741103
// Instead of retrieving an AppCredentials from the Adapter instance, generate a new one
10751104
const appPassword = await this.credentialsProvider.getAppPassword(appId);
1076-
return new MicrosoftAppCredentials(appId, appPassword, oAuthScope);
1105+
return new MicrosoftAppCredentials(appId, appPassword, undefined, oAuthScope);
10771106
}
10781107

10791108
/**

0 commit comments

Comments
 (0)