Skip to content

Commit

Permalink
address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Swagat Mishra committed Mar 2, 2020
1 parent 845069b commit 305103f
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 79 deletions.
7 changes: 4 additions & 3 deletions libraries/botbuilder-core/src/activityHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
import { ChannelAccount, MessageReaction, TurnContext } from '.';
import { ActivityHandlerBase } from './activityHandlerBase';
import { verifyStateOperationName, tokenExchangeOperationName, tokenResponseEventName } from './authContants';

/**
* Describes a bot activity event handler, for use with an [ActivityHandler](xref:botbuilder-core.ActivityHandler) object.
Expand Down Expand Up @@ -391,7 +392,6 @@ export class ActivityHandler extends ActivityHandlerBase {
* The default logic is to call any handlers registered via [onTurn](xref:botbuilder-core.ActivityHandler.onTurn),
* and then continue by calling [ActivityHandlerBase.onTurnActivity](xref:botbuilder-core.ActivityHandlerBase.onTurnActivity).
*/
//maybe handle invoke here instead of in base
protected async onTurnActivity(context: TurnContext): Promise<void> {
await this.handle(context, 'Turn', async () => {
await super.onTurnActivity(context);
Expand Down Expand Up @@ -426,13 +426,14 @@ export class ActivityHandler extends ActivityHandlerBase {
* and then continue by calling [defaultNextEvent](xref:botbuilder-core.ActivityHandler.defaultNextEvent).
*/
protected async onInvokeActivity(context: TurnContext): Promise<void|any> {
if(context.activity.name && context.activity.name === 'signin/verifyState' || context.activity.name === 'signin/tokenExchange') {
if(context.activity.name && context.activity.name === verifyStateOperationName || context.activity.name === tokenExchangeOperationName) {
await this.onSignInInvoke(context);
}
else {
await this.handle(context, 'Invoke', this.defaultNextEvent(context));
}
}

/*
* Runs all registered _signin invoke activity type_ handlers and then continues the event emission process.
*
Expand Down Expand Up @@ -648,7 +649,7 @@ export class ActivityHandler extends ActivityHandlerBase {
* - Continue by calling [defaultNextEvent](xref:botbuilder-core.ActivityHandler.defaultNextEvent).
*/
protected async dispatchEventActivity(context: TurnContext): Promise<void> {
if (context.activity.name === 'tokens/response') {
if (context.activity.name === tokenResponseEventName) {
await this.handle(context, 'TokenResponseEvent', this.defaultNextEvent(context));
} else {
await this.defaultNextEvent(context)();
Expand Down
11 changes: 11 additions & 0 deletions libraries/botbuilder-core/src/authContants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @module botbuilder
*/
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/

export const verifyStateOperationName: string = 'signin/verifyState';
export const tokenExchangeOperationName: string = 'signin/tokenExchange';
export const tokenResponseEventName: string = 'tokens/response';
49 changes: 0 additions & 49 deletions libraries/botbuilder-core/src/credentialTokenProvider.ts

This file was deleted.

6 changes: 3 additions & 3 deletions libraries/botbuilder-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
*/

export * from 'botframework-schema';
export * from './authContants';
export * from './appCredentials';
export * from './activityHandler';
export * from './activityHandlerBase';
export * from './autoSaveStateMiddleware';
Expand Down Expand Up @@ -35,6 +37,4 @@ export * from './transcriptLogger';
export * from './turnContext';
export * from './userState';
export * from './userTokenProvider';
export * from './userTokenSettings';
export * from './appCredentials';
export * from './credentialTokenProvider';
export * from './userTokenSettings';
9 changes: 5 additions & 4 deletions libraries/botbuilder-core/src/testAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,20 +396,21 @@ export class TestAdapter extends BotAdapter implements IExtendedUserTokenProvide
}


private _exchangeableTokens : {[key: string]: ExchangeableToken} = {};
private exchangeableTokens : {[key: string]: ExchangeableToken} = {};

public addExchangeableToken(connectionName: string, channelId: string, userId: string, exchangeableItem: string, token: string) {
const key: ExchangeableToken = new ExchangeableToken();
key.ChannelId = channelId;
key.ConnectionName = connectionName;
key.UserId = userId;
key.exchangeableItem = exchangeableItem;
key.Token = token;
this._exchangeableTokens[key.toKey()] = key;
this.exchangeableTokens[key.toKey()] = key;
}

public async getSignInResource(context: TurnContext, connectionName: string, userId?: string, finalRedirect?: string): Promise<BotSignInGetSignInResourceResponse> {
return {
signInLink: `https://fake.com/oauthsignin/${connectionName}/${context.activity.channelId}/${userId}`,
signInLink: `https://botframeworktestadapter.com/oauthsignin/${connectionName}/${context.activity.channelId}/${userId}`,
tokenExchangeResource: {
id: String(Math.random()),
providerId: null,
Expand All @@ -429,7 +430,7 @@ export class TestAdapter extends BotAdapter implements IExtendedUserTokenProvide
key.exchangeableItem = exchangeableValue;
key.UserId = userId;

const tokenExchangeResponse = this._exchangeableTokens[key.toKey()];
const tokenExchangeResponse = this.exchangeableTokens[key.toKey()];
return tokenExchangeResponse ?
{
channelId: key.ChannelId,
Expand Down
1 change: 1 addition & 0 deletions libraries/botbuilder-dialogs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@microsoft/recognizers-text-number": "1.1.4",
"@microsoft/recognizers-text-suite": "1.1.4",
"@types/node": "^10.12.18",
"botbuilder": "4.1.6",
"botbuilder-core": "4.1.6",
"globalize": "^1.4.2"
},
Expand Down
32 changes: 18 additions & 14 deletions libraries/botbuilder-dialogs/src/prompts/oauthPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { Activity, ActivityTypes, Attachment, AppCredentials, CardFactory, Channels, InputHints, MessageFactory, OAuthLoginTimeoutKey, TokenResponse, TurnContext, IUserTokenProvider, OAuthCard, ActionTypes, IExtendedUserTokenProvider } from 'botbuilder-core';
import { Activity, ActivityTypes, Attachment, AppCredentials, CardFactory, Channels, InputHints, MessageFactory, OAuthLoginTimeoutKey, TokenResponse, TurnContext, IUserTokenProvider, OAuthCard, ActionTypes, IExtendedUserTokenProvider, verifyStateOperationName, tokenExchangeOperationName, tokenResponseEventName } from 'botbuilder-core';
import { StatusCodes} from 'botbuilder';
import { Dialog, DialogTurnResult } from '../dialog';
import { DialogContext } from '../dialogContext';
import { PromptOptions, PromptRecognizerResult, PromptValidator } from './prompt';
Expand All @@ -28,7 +29,7 @@ class TokenExchangeInvokeResponse {
connectionName: string;
failureDetail: string;

constructor(id:string, connectionName:string, failureDetail:string){
constructor(id:string, connectionName:string, failureDetail:string) {
this.id = id;
this.connectionName = connectionName;
this.failureDetail = failureDetail;
Expand Down Expand Up @@ -333,7 +334,7 @@ export class OAuthPrompt extends Dialog {
try {
token = await this.getUserToken(context, code);
if (token !== undefined) {
await context.sendActivity({ type: 'invokeResponse', value: { status: 200 }});
await context.sendActivity({ type: 'invokeResponse', value: { status: StatusCodes }});
} else {
await context.sendActivity({ type: 'invokeResponse', value: { status: 404 }});
}
Expand All @@ -343,39 +344,42 @@ export class OAuthPrompt extends Dialog {
await context.sendActivity({ type: 'invokeResponse', value: { status: 500 }});
}
} else if (this.isTokenExchangeRequestInvoke(context)) {
// Received activity is not a token exchange request
if(!(context.activity.value && this.isTokenExchangeRequest(context.activity.value))) {
await context.sendActivity(this.getTokenExchangeInvokeResponse(
400,
StatusCodes.BAD_REQUEST,
'The bot received an InvokeActivity that is missing a TokenExchangeInvokeRequest value. This is required to be sent with the InvokeActivity.'));
} else if (context.activity.value.connectionName != this.settings.connectionName) {
} else if (context.activity.value.connectionName != this.settings.connectionName) {
// Connection name on activity does not match that of setting
await context.sendActivity(this.getTokenExchangeInvokeResponse(
400,
StatusCodes.BAD_REQUEST,
'The bot received an InvokeActivity with a TokenExchangeInvokeRequest containing a ConnectionName that does not match the ConnectionName' +
'expected by the bots active OAuthPrompt. Ensure these names match when sending the InvokeActivityInvalid ConnectionName in the TokenExchangeInvokeRequest'));
} else if (!('exchangeToken' in context.adapter)) {
// Token Exchange not supported in the adapter
await context.sendActivity(this.getTokenExchangeInvokeResponse(
502,
StatusCodes.BAD_GATEWAY,
'The bot\'s BotAdapter does not support token exchange operations. Ensure the bot\'s Adapter supports the ITokenExchangeProvider interface.'));
throw new Error('OAuthPrompt.recognize(): not supported by the current adapter');
} else {
// No errors. Proceed with token exchange
const extendedUserTokenProvider : IExtendedUserTokenProvider = context.adapter as IExtendedUserTokenProvider;
const tokenExchangeResponse = await extendedUserTokenProvider.exchangeToken(context, this.settings.connectionName, context.activity.from.id, {token: context.activity.value.token});

if(!tokenExchangeResponse || !tokenExchangeResponse.token) {
await context.sendActivity(this.getTokenExchangeInvokeResponse(
409,
StatusCodes.CONFLICT,
'The bot is unable to exchange token. Proceed with regular login.'));
} else {
await context.sendActivity(this.getTokenExchangeInvokeResponse(200, null, context.activity.value.id));
await context.sendActivity(this.getTokenExchangeInvokeResponse(StatusCodes.OK, null, context.activity.value.id));
token = {
channelId: tokenExchangeResponse.channelId,
connectionName: tokenExchangeResponse.connectionName,
token : tokenExchangeResponse.token,
expiration: null
};
};
}
}

} else if (context.activity.type === ActivityTypes.Message) {
const matched: RegExpExecArray = /(\d{6})/.exec(context.activity.text);
if (matched && matched.length > 1) {
Expand All @@ -400,19 +404,19 @@ export class OAuthPrompt extends Dialog {
private isTokenResponseEvent(context: TurnContext): boolean {
const activity: Activity = context.activity;

return activity.type === ActivityTypes.Event && activity.name === 'tokens/response';
return activity.type === ActivityTypes.Event && activity.name === tokenResponseEventName;
}

private isTeamsVerificationInvoke(context: TurnContext): boolean {
const activity: Activity = context.activity;

return activity.type === ActivityTypes.Invoke && activity.name === 'signin/verifyState';
return activity.type === ActivityTypes.Invoke && activity.name === verifyStateOperationName;
}

private isTokenExchangeRequestInvoke(context: TurnContext): boolean {
const activity: Activity = context.activity;

return activity.type === ActivityTypes.Invoke && activity.name === 'signin/tokenExchange';
return activity.type === ActivityTypes.Invoke && activity.name === tokenExchangeOperationName;
}

private isTokenExchangeRequest(obj: unknown) : obj is TokenExchangeInvokeRequest {
Expand Down
7 changes: 5 additions & 2 deletions libraries/botbuilder/src/botFrameworkAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ export enum StatusCodes {
UNAUTHORIZED = 401,
NOT_FOUND = 404,
METHOD_NOT_ALLOWED = 405,
CONFLICT = 409,
UPGRADE_REQUIRED = 426,
INTERNAL_SERVER_ERROR = 500,
NOT_IMPLEMENTED = 501,
BAD_GATEWAY = 502
}

export class StatusCodeError extends Error {
Expand Down Expand Up @@ -597,7 +599,8 @@ export class BotFrameworkAdapter extends BotAdapter implements IExtendedUserToke
const state: any = {
ConnectionName: connectionName,
Conversation: conversation,
MsAppId: (client.credentials as AppCredentials).appId
MsAppId: (client.credentials as AppCredentials).appId,
RelatesTo: context.activity.relatesTo
};

const finalState: string = Buffer.from(JSON.stringify(state)).toString('base64');
Expand Down Expand Up @@ -688,7 +691,7 @@ export class BotFrameworkAdapter extends BotAdapter implements IExtendedUserToke
const state: any = {
ConnectionName: connectionName,
Conversation: conversation,
//RelatesTo = context.activity.RelatesTo,
relatesTo: context.activity.relatesTo,
MSAppId: (client.credentials as AppCredentials).appId
};
const finalState: string = Buffer.from(JSON.stringify(state)).toString('base64');
Expand Down
17 changes: 17 additions & 0 deletions libraries/botbuilder/src/botFrameworkHttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {

import { USER_AGENT } from './botFrameworkAdapter';
import { InvokeResponse } from './interfaces';
import { ConversationReference } from 'botframework-connector/lib/connectorApi/models/mappers';

/**
* HttpClient for calling skills from a Node.js BotBuilder V4 SDK bot.
Expand Down Expand Up @@ -68,6 +69,22 @@ export class BotFrameworkHttpClient {
const originalServiceUrl = activity.serviceUrl;
const originalCallerId = activity.callerId;
try {
activity.relatesTo = {
serviceUrl: activity.serviceUrl,
activityId: activity.id,
channelId: activity.channelId,
conversation: {
id: activity.conversation.id,
name: activity.conversation.name,
conversationType: activity.conversation.conversationType,
aadObjectId: activity.conversation.aadObjectId,
isGroup: activity.conversation.isGroup,
properties: activity.conversation.properties,
role: activity.conversation.role,
tenantId: activity.conversation.tenantId
},
bot: null
};
activity.conversation.id = conversationId;
activity.serviceUrl = serviceUrl;
activity.callerId = fromBotId;
Expand Down
3 changes: 2 additions & 1 deletion libraries/botbuilder/src/streaming/tokenResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
TokenPollingSettings,
TokenPollingSettingsKey,
TurnContext,
tokenResponseEventName,
} from 'botbuilder-core';

/**
Expand Down Expand Up @@ -104,7 +105,7 @@ export class TokenResolver {
replyToId: relatesTo.activityId,
channelId: relatesTo.channelId,
conversation: relatesTo.conversation,
name: 'tokens/response',
name: tokenResponseEventName,
relatesTo: <ConversationReference>relatesTo,
value: {
token: token,
Expand Down
8 changes: 5 additions & 3 deletions libraries/botbuilder/src/teamsActivityHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ import {
TeamsChannelData,
TeamsChannelAccount,
TeamInfo,
TurnContext
TurnContext,
tokenExchangeOperationName,
verifyStateOperationName
} from 'botbuilder-core';
import { InvokeResponse } from './interfaces';
import { TeamsInfo } from './teamsInfo';
Expand Down Expand Up @@ -62,11 +64,11 @@ export class TeamsActivityHandler extends ActivityHandler {
return await this.handleTeamsCardActionInvoke(context);
} else {
switch (context.activity.name) {
case 'signin/verifyState':
case verifyStateOperationName:
await this.handleTeamsSigninVerifyState(context, context.activity.value);
return TeamsActivityHandler.createInvokeResponse();

case 'signin/tokenExchange':
case tokenExchangeOperationName:
await this.handleTeamsSigninTokenExchange(context, context.activity.value);
return TeamsActivityHandler.createInvokeResponse();

Expand Down

0 comments on commit 305103f

Please sign in to comment.