Skip to content

Commit

Permalink
Cherry-picks #1902 and #1894 to master (#1906)
Browse files Browse the repository at this point in the history
* Revert breaking changes around BotFrameworkClient implementations (#1894)

* change BotFrameworkClient to interface
* postActivity property is now a Union type

* fix breaking change in SkillHttpClient

* fix private isEocComingFromParent in dialogHelper.ts

* Fix AppCredentials compilation error in BotFrameworkAdapter (#1902)

* implement different fixes for #1901

* loosen credentials reqs in BFHttpClient

* rev on BotFrameworkAdapter AppCredentials fix

* fix breaking change in createTokenApiClient

* rename CoreAppCredentials

* make appCredentials optional in oAuthPromptSettings

* test: add typescript consumer test (#1904)

Co-authored-by: stevengum <14935595+stevengum@users.noreply.github.com>

Co-authored-by: Christopher Anderson <chrande@microsoft.com>

Co-authored-by: Christopher Anderson <chrande@microsoft.com>
  • Loading branch information
stevengum and Christopher Anderson authored Mar 13, 2020
1 parent 20394bd commit 2d5a230
Show file tree
Hide file tree
Showing 12 changed files with 150 additions and 51 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -313,3 +313,6 @@ package-lock.json

*.tsbuildinfo
*.js.map

consumer-test/**.js
consumer-test/**.json
27 changes: 27 additions & 0 deletions consumer-test/test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import * as l1 from '../libraries/adaptive-expressions';
import * as l2 from '../libraries/botbuilder';
import * as l3 from '../libraries/botbuilder-ai';
import * as l4 from '../libraries/botbuilder-applicationinsights';
import * as l5 from '../libraries/botbuilder-azure';
import * as l6 from '../libraries/botbuilder-core';
import * as l7 from '../libraries/botbuilder-dialogs';
import * as l8 from '../libraries/botbuilder-lg';
import * as l9 from '../libraries/botbuilder-testing';
import * as l10 from '../libraries/botframework-config';
import * as l11 from '../libraries/botframework-connector';
import * as l13 from '../libraries/botframework-schema';
import * as l14 from '../libraries/botframework-streaming';

console.log(Object.keys(l1));
console.log(Object.keys(l2));
console.log(Object.keys(l3));
console.log(Object.keys(l4));
console.log(Object.keys(l5));
console.log(Object.keys(l6));
console.log(Object.keys(l7));
console.log(Object.keys(l8));
console.log(Object.keys(l9));
console.log(Object.keys(l10));
console.log(Object.keys(l11));
console.log(Object.keys(l13));
console.log(Object.keys(l14));
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,28 @@
* Licensed under the MIT License.
*/

/**
* Internal interface representing the "WebResource" from @azure/ms-rest-js@1.2.6
*/
interface WebResource {}
/**
* Internal interface representing the "WebResource" from @azure/ms-rest-js@1.2.6
*/
interface CoreWebResource {
url?: string;
method?: any;
body?: any;
headers?: any;
}


/**
* AppCredentials
* CoreAppCredentials
* @remarks
* Runtime-agnostic interface representing "ServiceClientCredentials" from @azure/ms-rest-js@1.2.6
*/
export interface AppCredentials {
export interface CoreAppCredentials {
/**
* Signs a request with the Authentication header.
*
* @param {WebResource} webResource The WebResource/request to be signed.
* @returns {Promise<WebResource>} The signed request object;
*/
signRequest(webResource: WebResource): Promise<WebResource>;
signRequest(webResource: CoreWebResource): Promise<CoreWebResource>;
}
14 changes: 7 additions & 7 deletions libraries/botbuilder-core/src/extendedUserTokenProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* Licensed under the MIT License.
*/

import { AppCredentials } from './appCredentials';
import { CoreAppCredentials } from './coreAppCredentials';
import { IUserTokenProvider } from './userTokenProvider';
import { TurnContext } from './turnContext';
import { SignInUrlResponse ,TokenResponse, TokenExchangeRequest } from 'botframework-schema';
Expand All @@ -21,7 +21,7 @@ export interface ExtendedUserTokenProvider extends IUserTokenProvider {
* @param connectionName Name of the auth connection to use.
* @param magicCode (Optional) Optional user entered code to validate.
*/
getUserToken(context: TurnContext, connectionName: string, magicCode?: string, appCredentials?: AppCredentials): Promise<TokenResponse>;
getUserToken(context: TurnContext, connectionName: string, magicCode?: string, appCredentials?: CoreAppCredentials): Promise<TokenResponse>;

/**
* Signs the user out with the token server.
Expand All @@ -30,23 +30,23 @@ export interface ExtendedUserTokenProvider extends IUserTokenProvider {
* @param userId User id of user to sign out.
* @param oAuthAppCredentials AppCredentials for OAuth.
*/
signOutUser(context: TurnContext, connectionName: string, userId?: string, appCredentials?: AppCredentials): Promise<void>;
signOutUser(context: TurnContext, connectionName: string, userId?: string, appCredentials?: CoreAppCredentials): Promise<void>;

/**
* Gets a signin link from the token server that can be sent as part of a SigninCard.
* @param context Context for the current turn of conversation with the user.
* @param connectionName Name of the auth connection to use.
* @param oAuthAppCredentials AppCredentials for OAuth.
*/
getSignInLink(context: TurnContext, connectionName: string, appCredentials?: AppCredentials): Promise<string>;
getSignInLink(context: TurnContext, connectionName: string, appCredentials?: CoreAppCredentials): Promise<string>;

/**
* Signs the user out with the token server.
* @param context Context for the current turn of conversation with the user.
* @param connectionName Name of the auth connection to use.
* @param oAuthAppCredentials AppCredentials for OAuth.
*/
getAadTokens(context: TurnContext, connectionName: string, resourceUrls: string[], appCredentials?: AppCredentials): Promise<{
getAadTokens(context: TurnContext, connectionName: string, resourceUrls: string[], appCredentials?: CoreAppCredentials): Promise<{
[propertyName: string]: TokenResponse;
}>;

Expand All @@ -73,7 +73,7 @@ export interface ExtendedUserTokenProvider extends IUserTokenProvider {
* @param userId The user id that will be associated with the token.
* @param finalRedirect The final URL that the OAuth flow will redirect to.
*/
getSignInResource(context: TurnContext, connectionName: string, userId: string, finalRedirect?: string, appCredentials?: AppCredentials): Promise<SignInUrlResponse>;
getSignInResource(context: TurnContext, connectionName: string, userId: string, finalRedirect?: string, appCredentials?: CoreAppCredentials): Promise<SignInUrlResponse>;

/**
* Performs a token exchange operation such as for single sign-on.
Expand All @@ -91,5 +91,5 @@ export interface ExtendedUserTokenProvider extends IUserTokenProvider {
* @param userId The user id that will be associated with the token.
* @param tokenExchangeRequest The exchange request details, either a token to exchange or a uri to exchange.
*/
exchangeToken(context: TurnContext, connectionName: string, userId: string, tokenExchangeRequest: TokenExchangeRequest, appCredentials: AppCredentials): Promise<TokenResponse>;
exchangeToken(context: TurnContext, connectionName: string, userId: string, tokenExchangeRequest: TokenExchangeRequest, appCredentials: CoreAppCredentials): Promise<TokenResponse>;
}
8 changes: 6 additions & 2 deletions libraries/botbuilder-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

export * from 'botframework-schema';
export * from './activityFactory';
export * from './appCredentials';
export * from './coreAppCredentials';
export * from './activityHandler';
export * from './activityHandlerBase';
export * from './autoSaveStateMiddleware';
Expand All @@ -31,7 +31,11 @@ export * from './propertyManager';
export * from './recognizerResult';
export * from './showTypingMiddleware';
export * from './signInConstants';
export { BotFrameworkSkill, BotFrameworkClient, SkillConversationIdFactoryBase, SkillConversationReference,
export {
BotFrameworkSkill,
BotFrameworkClient,
SkillConversationIdFactoryBase,
SkillConversationReference,
SkillConversationIdFactoryOptions } from './skills';
export * from './skypeMentionNormalizeMiddleware';
export * from './statusCodes';
Expand Down
4 changes: 2 additions & 2 deletions libraries/botbuilder-core/src/skills/botFrameworkClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { Activity } from 'botframework-schema';
import { InvokeResponse } from '../invokeResponse';

export abstract class BotFrameworkClient {
export interface BotFrameworkClient {
/**
* Forwards an activity to a another bot.
* @remarks
Expand All @@ -21,5 +21,5 @@ export abstract class BotFrameworkClient {
* @param conversationId A conversation ID to use for the conversation with the skill.
* @param activity Activity to forward.
*/
public abstract postActivity<T>(fromBotId: string, toBotId: string, toUrl: string, serviceUrl: string, conversationId: string, activity: Activity): Promise<InvokeResponse<T>>
postActivity: (<T>(fromBotId: string, toBotId: string, toUrl: string, serviceUrl: string, conversationId: string, activity: Activity) => Promise<InvokeResponse<T>>) | ((fromBotId: string, toBotId: string, toUrl: string, serviceUrl: string, conversationId: string, activity: Activity) => Promise<InvokeResponse>);
}
4 changes: 2 additions & 2 deletions libraries/botbuilder-dialogs/src/prompts/oauthPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
import { Activity, ActivityTypes, Attachment, AppCredentials, BotAdapter, CardFactory, Channels, InputHints, MessageFactory, OAuthLoginTimeoutKey, TokenResponse, TurnContext, OAuthCard, ActionTypes, ExtendedUserTokenProvider, verifyStateOperationName, StatusCodes, tokenExchangeOperationName, tokenResponseEventName } from 'botbuilder-core';
import { Activity, ActivityTypes, Attachment, CoreAppCredentials, BotAdapter, CardFactory, Channels, InputHints, MessageFactory, OAuthLoginTimeoutKey, TokenResponse, TurnContext, OAuthCard, ActionTypes, ExtendedUserTokenProvider, verifyStateOperationName, StatusCodes, tokenExchangeOperationName, tokenResponseEventName } from 'botbuilder-core';
import { Dialog, DialogTurnResult } from '../dialog';
import { DialogContext } from '../dialogContext';
import { PromptOptions, PromptRecognizerResult, PromptValidator } from './prompt';
Expand Down Expand Up @@ -42,7 +42,7 @@ export interface OAuthPromptSettings {
/**
* AppCredentials for OAuth.
*/
oAuthAppCredentials: AppCredentials;
oAuthAppCredentials?: CoreAppCredentials;

/**
* Name of the OAuth connection being used.
Expand Down
28 changes: 16 additions & 12 deletions libraries/botbuilder/src/botFrameworkAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { STATUS_CODES } from 'http';
import * as os from 'os';

import { Activity, ActivityTypes, BotAdapter, BotCallbackHandlerKey, ChannelAccount, ConversationAccount, ConversationParameters, ConversationReference, ConversationsResult, DeliveryModes, ExpectedReplies, InvokeResponse, ExtendedUserTokenProvider, ResourceResponse, StatusCodes, TokenResponse, TurnContext, INVOKE_RESPONSE_KEY } from 'botbuilder-core';
import { Activity, ActivityTypes, CoreAppCredentials, BotAdapter, BotCallbackHandlerKey, ChannelAccount, ConversationAccount, ConversationParameters, ConversationReference, ConversationsResult, DeliveryModes, ExpectedReplies, InvokeResponse, ExtendedUserTokenProvider, ResourceResponse, StatusCodes, TokenResponse, TurnContext, INVOKE_RESPONSE_KEY } from 'botbuilder-core';
import { AuthenticationConfiguration, AuthenticationConstants, ChannelValidation, Claim, ClaimsIdentity, ConnectorClient, EmulatorApiClient, GovernmentConstants, GovernmentChannelValidation, JwtTokenValidation, MicrosoftAppCredentials, AppCredentials, CertificateAppCredentials, SimpleCredentialProvider, TokenApiClient, TokenStatus, TokenApiModels, SignInUrlResponse, SkillValidation, TokenExchangeRequest } from 'botframework-connector';

import { INodeBuffer, INodeSocket, IReceiveRequest, ISocket, IStreamingTransportServer, NamedPipeServer, NodeWebSocketFactory, NodeWebSocketFactoryBase, RequestHandler, StreamingResponse, WebSocketServer } from 'botframework-streaming';
Expand Down Expand Up @@ -537,7 +537,7 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
* @returns A [TokenResponse](xref:botframework-schema.TokenResponse) object that contains the user token.
*/
public async getUserToken(context: TurnContext, connectionName: string, magicCode?: string): Promise<TokenResponse>;
public async getUserToken(context: TurnContext, connectionName: string, magicCode?: string, oAuthAppCredentials?: AppCredentials): Promise<TokenResponse>;
public async getUserToken(context: TurnContext, connectionName: string, magicCode?: string, oAuthAppCredentials?: CoreAppCredentials): Promise<TokenResponse>;
public async getUserToken(context: TurnContext, connectionName: string, magicCode?: string, oAuthAppCredentials?: AppCredentials): Promise<TokenResponse> {
if (!context.activity.from || !context.activity.from.id) {
throw new Error(`BotFrameworkAdapter.getUserToken(): missing from or from.id`);
Expand Down Expand Up @@ -568,7 +568,7 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
* @param oAuthAppCredentials AppCredentials for OAuth.
*/
public async signOutUser(context: TurnContext, connectionName?: string, userId?: string): Promise<void>;
public async signOutUser(context: TurnContext, connectionName?: string, userId?: string, oAuthAppCredentials?: AppCredentials): Promise<void>;
public async signOutUser(context: TurnContext, connectionName?: string, userId?: string, oAuthAppCredentials?: CoreAppCredentials): Promise<void>;
public async signOutUser(context: TurnContext, connectionName?: string, userId?: string, oAuthAppCredentials?: AppCredentials): Promise<void> {
if (!context.activity.from || !context.activity.from.id) {
throw new Error(`BotFrameworkAdapter.signOutUser(): missing from or from.id`);
Expand All @@ -595,6 +595,8 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
* @param userId The user id that will be associated with the token.
* @param finalRedirect The final URL that the OAuth flow will redirect to.
*/
public async getSignInLink(context: TurnContext, connectionName: string, oAuthAppCredentials?: AppCredentials, userId?: string, finalRedirect?: string): Promise<string>
public async getSignInLink(context: TurnContext, connectionName: string, oAuthAppCredentials?: CoreAppCredentials, userId?: string, finalRedirect?: string): Promise<string>
public async getSignInLink(context: TurnContext, connectionName: string, oAuthAppCredentials?: AppCredentials, userId?: string, finalRedirect?: string): Promise<string> {
if (userId && userId != context.activity.from.id) {
throw new ReferenceError(`cannot retrieve OAuth signin link for a user that's different from the conversation`);
Expand Down Expand Up @@ -629,7 +631,7 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
* @returns The [TokenStatus](xref:botframework-connector.TokenStatus) objects retrieved.
*/
public async getTokenStatus(context: TurnContext, userId?: string, includeFilter?: string): Promise<TokenStatus[]>;
public async getTokenStatus(context: TurnContext, userId?: string, includeFilter?: string, oAuthAppCredentials?: AppCredentials): Promise<TokenStatus[]>;
public async getTokenStatus(context: TurnContext, userId?: string, includeFilter?: string, oAuthAppCredentials?: CoreAppCredentials): Promise<TokenStatus[]>;
public async getTokenStatus(context: TurnContext, userId?: string, includeFilter?: string, oAuthAppCredentials?: AppCredentials): Promise<TokenStatus[]> {
if (!userId && (!context.activity.from || !context.activity.from.id)) {
throw new Error(`BotFrameworkAdapter.getTokenStatus(): missing from or from.id`);
Expand All @@ -654,7 +656,7 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
* @returns A map of the [TokenResponse](xref:botframework-schema.TokenResponse) objects by resource URL.
*/
public async getAadTokens(context: TurnContext, connectionName: string, resourceUrls: string[]): Promise<{[propertyName: string]: TokenResponse}>;
public async getAadTokens(context: TurnContext, connectionName: string, resourceUrls: string[], oAuthAppCredentials?: AppCredentials): Promise<{[propertyName: string]: TokenResponse}>;
public async getAadTokens(context: TurnContext, connectionName: string, resourceUrls: string[], oAuthAppCredentials?: CoreAppCredentials): Promise<{[propertyName: string]: TokenResponse}>;
public async getAadTokens(context: TurnContext, connectionName: string, resourceUrls: string[], oAuthAppCredentials?: AppCredentials): Promise<{[propertyName: string]: TokenResponse}> {
if (!context.activity.from || !context.activity.from.id) {
throw new Error(`BotFrameworkAdapter.getAadTokens(): missing from or from.id`);
Expand All @@ -678,8 +680,7 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
*
* @returns The [BotSignInGetSignInResourceResponse](xref:botframework-connector.BotSignInGetSignInResourceResponse) object.
*/
public async getSignInResource(context: TurnContext, connectionName: string, userId?: string, finalRedirect?: string, appCredentials?: AppCredentials): Promise<SignInUrlResponse>
{
public async getSignInResource(context: TurnContext, connectionName: string, userId?: string, finalRedirect?: string, appCredentials?: CoreAppCredentials): Promise<SignInUrlResponse> {
if (!connectionName) {
throw new Error('getUserToken() requires a connectionName but none was provided.');
}
Expand All @@ -688,13 +689,14 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
throw new Error(`BotFrameworkAdapter.getSignInResource(): missing from or from.id`);
}

// what to do when userId is null (same for finalRedirect)
if(userId && context.activity.from.id != userId) {
// The provided userId doesn't match the from.id on the activity. (same for finalRedirect)
if (userId && context.activity.from.id !== userId) {
throw new Error('BotFrameworkAdapter.getSiginInResource(): cannot get signin resource for a user that is different from the conversation');
}

const url: string = this.oauthApiUrl(context);
const client: TokenApiClient = this.createTokenApiClient(url, appCredentials);
const credentials = appCredentials as AppCredentials;
const client: TokenApiClient = this.createTokenApiClient(url, credentials);
const conversation: Partial<ConversationReference> = TurnContext.getConversationReference(context.activity);

const state: any = {
Expand All @@ -716,6 +718,7 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
* @param userId The user id that will be associated with the token.
* @param tokenExchangeRequest The exchange request details, either a token to exchange or a uri to exchange.
*/
public async exchangeToken(context: TurnContext, connectionName: string, userId: string, tokenExchangeRequest: TokenExchangeRequest, appCredentials?: CoreAppCredentials): Promise<TokenResponse>
public async exchangeToken(context: TurnContext, connectionName: string, userId: string, tokenExchangeRequest: TokenExchangeRequest, appCredentials?: AppCredentials): Promise<TokenResponse> {
if (!connectionName) {
throw new Error('exchangeToken() requires a connectionName but none was provided.');
Expand Down Expand Up @@ -749,7 +752,7 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
public async emulateOAuthCards(contextOrServiceUrl: TurnContext | string, emulate: boolean): Promise<void> {
this.isEmulatingOAuthCards = emulate;
const url: string = this.oauthApiUrl(contextOrServiceUrl);
await EmulatorApiClient.emulateOAuthCards(this.credentials as AppCredentials, url, emulate);
await EmulatorApiClient.emulateOAuthCards(this.credentials, url, emulate);
}

/**
Expand Down Expand Up @@ -1126,7 +1129,8 @@ export class BotFrameworkAdapter extends BotAdapter implements ExtendedUserToken
* @remarks
* Override this in a derived class to create a mock OAuth API client for unit testing.
*/
protected createTokenApiClient(serviceUrl: string, oAuthAppCredentials: AppCredentials): TokenApiClient {
protected createTokenApiClient(serviceUrl: string, oAuthAppCredentials?: CoreAppCredentials): TokenApiClient;
protected createTokenApiClient(serviceUrl: string, oAuthAppCredentials?: AppCredentials): TokenApiClient {
const tokenApiClientCredentials = oAuthAppCredentials ? oAuthAppCredentials : this.credentials;
const client = new TokenApiClient(tokenApiClientCredentials, { baseUri: serviceUrl, userAgent: USER_AGENT });

Expand Down
Loading

0 comments on commit 2d5a230

Please sign in to comment.