diff --git a/libraries/botbuilder-core/src/appCredentials.ts b/libraries/botbuilder-core/src/appCredentials.ts new file mode 100644 index 0000000000..77f26b85fd --- /dev/null +++ b/libraries/botbuilder-core/src/appCredentials.ts @@ -0,0 +1,27 @@ +/** + * @module botbuilder-core + */ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + + /** + * Internal interface representing the "WebResource" from @azure/ms-rest-js@1.2.6 + */ +interface WebResource {} + +/** + * AppCredentials + * @remarks + * Runtime-agnostic interface representing "ServiceClientCredentials" from @azure/ms-rest-js@1.2.6 + */ +export interface AppCredentials { + /** + * Signs a request with the Authentication header. + * + * @param {WebResource} webResource The WebResource/request to be signed. + * @returns {Promise} The signed request object; + */ + signRequest(webResource: WebResource): Promise; +} diff --git a/libraries/botbuilder-core/src/credentialTokenProvider.ts b/libraries/botbuilder-core/src/credentialTokenProvider.ts new file mode 100644 index 0000000000..8e918748f9 --- /dev/null +++ b/libraries/botbuilder-core/src/credentialTokenProvider.ts @@ -0,0 +1,49 @@ +/** + * @module botbuilder-core + */ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. + */ + +import { AppCredentials } from './appCredentials'; +import { IUserTokenProvider } from './userTokenProvider'; +import { TurnContext } from './turnContext'; +import { TokenResponse } from 'botframework-schema'; + +export interface CredentialTokenProvider extends IUserTokenProvider { + /** + * Retrieves the OAuth token for a user that is in a sign-in flow. + * @param context Context for the current turn of conversation with the user. + * @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; + + /** + * 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 userId User id of user to sign out. + * @param oAuthAppCredentials AppCredentials for OAuth. + */ + signOutUser(context: TurnContext, connectionName: string, userId?: string, appCredentials?: AppCredentials): Promise; + + /** + * 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; + + /** + * 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<{ + [propertyName: string]: TokenResponse; + }>; +} diff --git a/libraries/botbuilder-core/src/index.ts b/libraries/botbuilder-core/src/index.ts index 74ea0624c2..f84e05cf12 100644 --- a/libraries/botbuilder-core/src/index.ts +++ b/libraries/botbuilder-core/src/index.ts @@ -35,3 +35,5 @@ export * from './turnContext'; export * from './userState'; export * from './userTokenProvider'; export * from './userTokenSettings'; +export * from './appCredentials'; +export * from './credentialTokenProvider'; diff --git a/libraries/botbuilder-core/src/userTokenProvider.ts b/libraries/botbuilder-core/src/userTokenProvider.ts index 3367ffadfa..c457cbf927 100644 --- a/libraries/botbuilder-core/src/userTokenProvider.ts +++ b/libraries/botbuilder-core/src/userTokenProvider.ts @@ -25,8 +25,9 @@ export interface IUserTokenProvider { * 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 userId User id of user to sign out. */ - signOutUser(context: TurnContext, connectionName: string): Promise; + signOutUser(context: TurnContext, connectionName: string, userId?: string): Promise; /** * Gets a signin link from the token server that can be sent as part of a SigninCard. @@ -44,4 +45,3 @@ export interface IUserTokenProvider { [propertyName: string]: TokenResponse; }>; } - diff --git a/libraries/botbuilder-core/src/userTokenSettings.ts b/libraries/botbuilder-core/src/userTokenSettings.ts index 64fb7c9143..3a7f8b8849 100644 --- a/libraries/botbuilder-core/src/userTokenSettings.ts +++ b/libraries/botbuilder-core/src/userTokenSettings.ts @@ -9,8 +9,7 @@ /** * Provides details for token polling. */ -export interface TokenPollingSettings -{ +export interface TokenPollingSettings { /** * Polling timeout time in milliseconds. This is equivalent to login flow timeout. */ @@ -30,8 +29,7 @@ export const OAuthLoginTimeoutKey: string = 'loginTimeout'; /** * Name of the token polling settings key. */ -export const TokenPollingSettingsKey: string = "tokenPollingSettings"; - +export const TokenPollingSettingsKey: string = 'tokenPollingSettings'; /** * Default amount of time an OAuthCard will remain active (clickable and actively waiting for a token). @@ -39,4 +37,4 @@ export const TokenPollingSettingsKey: string = "tokenPollingSettings"; * (1) the OAuthCard will not allow the user to click on it. * (2) any polling triggered by the OAuthCard will stop. */ - export const OAuthLoginTimeoutMsValue: number = 900000; \ No newline at end of file + export const OAuthLoginTimeoutMsValue: number = 900000; diff --git a/libraries/botbuilder-dialogs/src/prompts/oauthPrompt.ts b/libraries/botbuilder-dialogs/src/prompts/oauthPrompt.ts index 4d927a5fec..51b92c943d 100644 --- a/libraries/botbuilder-dialogs/src/prompts/oauthPrompt.ts +++ b/libraries/botbuilder-dialogs/src/prompts/oauthPrompt.ts @@ -5,7 +5,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ -import { Activity, ActivityTypes, Attachment, CardFactory, Channels, InputHints, MessageFactory, OAuthLoginTimeoutKey, TokenResponse, TurnContext, IUserTokenProvider, OAuthCard, ActionTypes, } from 'botbuilder-core'; +import { Activity, ActivityTypes, AppCredentials, Attachment, CardFactory, Channels, InputHints, MessageFactory, OAuthLoginTimeoutKey, TokenResponse, TurnContext, CredentialTokenProvider, OAuthCard, ActionTypes, } from 'botbuilder-core'; import { Dialog, DialogTurnResult } from '../dialog'; import { DialogContext } from '../dialogContext'; import { PromptOptions, PromptRecognizerResult, PromptValidator } from './prompt'; @@ -15,6 +15,11 @@ import { isSkillClaim } from './skillsHelpers'; * Settings used to configure an `OAuthPrompt` instance. */ export interface OAuthPromptSettings { + /** + * AppCredentials for OAuth. + */ + oAuthAppCredentials: AppCredentials; + /** * Name of the OAuth connection being used. */ @@ -104,7 +109,6 @@ export interface OAuthPromptSettings { * ``` */ export class OAuthPrompt extends Dialog { - /** * Creates a new OAuthPrompt instance. * @param dialogId Unique ID of the dialog within its parent `DialogSet` or `ComponentDialog`. @@ -201,9 +205,9 @@ export class OAuthPrompt extends Dialog { } // Get the token and call validator - const adapter: IUserTokenProvider = context.adapter as IUserTokenProvider; + const adapter: CredentialTokenProvider = context.adapter as CredentialTokenProvider; - return await adapter.getUserToken(context, this.settings.connectionName, code); + return await adapter.getUserToken(context, this.settings.connectionName, code, this.settings.oAuthAppCredentials); } /** @@ -228,9 +232,9 @@ export class OAuthPrompt extends Dialog { } // Sign out user - const adapter: IUserTokenProvider = context.adapter as IUserTokenProvider; + const adapter: CredentialTokenProvider = context.adapter as CredentialTokenProvider; - return adapter.signOutUser(context, this.settings.connectionName); + return adapter.signOutUser(context, this.settings.connectionName, null, this.settings.oAuthAppCredentials); } private async sendOAuthCardAsync(context: TurnContext, prompt?: string|Partial): Promise { @@ -251,14 +255,14 @@ export class OAuthPrompt extends Dialog { let cardActionType = ActionTypes.Signin; let link: string; if (OAuthPrompt.isFromStreamingConnection(context.activity)) { - link = await (context.adapter as any).getSignInLink(context, this.settings.connectionName); + link = await (context.adapter as CredentialTokenProvider).getSignInLink(context, this.settings.connectionName, this.settings.oAuthAppCredentials); } else { // Retrieve the ClaimsIdentity from a BotFrameworkAdapter. For more information see // https://github.com/microsoft/botbuilder-js/commit/b7932e37bb6e421985d5ce53edd9e82af6240a63#diff-3e3af334c0c6adf4906ee5e2a23beaebR250 const identity = context.turnState.get((context.adapter as any).BotIdentityKey); if (identity && isSkillClaim(identity.claims)) { // Force magic code for Skills (to be addressed in R8) - link = await (context.adapter as any).getSignInLink(context, this.settings.connectionName); + link = await (context.adapter as CredentialTokenProvider).getSignInLink(context, this.settings.connectionName, this.settings.oAuthAppCredentials); cardActionType = ActionTypes.OpenUrl; } } @@ -278,7 +282,7 @@ export class OAuthPrompt extends Dialog { const cards: Attachment[] = msg.attachments.filter((a: Attachment) => a.contentType === CardFactory.contentTypes.signinCard); if (cards.length === 0) { // Append signin card - const link: any = await (context.adapter as any).getSignInLink(context, this.settings.connectionName); + const link: any = await (context.adapter as CredentialTokenProvider).getSignInLink(context, this.settings.connectionName, this.settings.oAuthAppCredentials); msg.attachments.push(CardFactory.signinCard( this.settings.title, link, diff --git a/libraries/botbuilder/src/botFrameworkAdapter.ts b/libraries/botbuilder/src/botFrameworkAdapter.ts index 3fc7d305fb..a55d750d05 100644 --- a/libraries/botbuilder/src/botFrameworkAdapter.ts +++ b/libraries/botbuilder/src/botFrameworkAdapter.ts @@ -9,7 +9,7 @@ import { STATUS_CODES } from 'http'; import * as os from 'os'; -import { Activity, ActivityTypes, BotAdapter, BotCallbackHandlerKey, ChannelAccount, ConversationAccount, ConversationParameters, ConversationReference, ConversationsResult, IUserTokenProvider, ResourceResponse, TokenResponse, TurnContext } from 'botbuilder-core'; +import { Activity, ActivityTypes, BotAdapter, BotCallbackHandlerKey, ChannelAccount, ConversationAccount, ConversationParameters, ConversationReference, ConversationsResult, CredentialTokenProvider, ResourceResponse, TokenResponse, TurnContext } from 'botbuilder-core'; import { AuthenticationConfiguration, AuthenticationConstants, ChannelValidation, ClaimsIdentity, ConnectorClient, EmulatorApiClient, GovernmentConstants, GovernmentChannelValidation, JwtTokenValidation, MicrosoftAppCredentials, AppCredentials, CertificateAppCredentials, SimpleCredentialProvider, TokenApiClient, TokenStatus, TokenApiModels, SkillValidation } from 'botframework-connector'; import { INodeBuffer, INodeSocket, IReceiveRequest, ISocket, IStreamingTransportServer, NamedPipeServer, NodeWebSocketFactory, NodeWebSocketFactoryBase, RequestHandler, StreamingResponse, WebSocketServer } from 'botframework-streaming'; @@ -139,12 +139,13 @@ export const INVOKE_RESPONSE_KEY: symbol = Symbol('invokeResponse'); * }; * ``` */ -export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvider, RequestHandler { +export class BotFrameworkAdapter extends BotAdapter implements CredentialTokenProvider, RequestHandler { // These keys are public to permit access to the keys from the adapter when it's a being // from library that does not have access to static properties off of BotFrameworkAdapter. // E.g. botbuilder-dialogs public readonly BotIdentityKey: Symbol = Symbol('BotIdentity'); public readonly ConnectorClientKey: Symbol = Symbol('ConnectorClient'); + public readonly TokenApiClientCredentialsKey: Symbol = Symbol('TokenApiClientCredentials'); protected readonly credentials: AppCredentials; protected readonly credentialsProvider: SimpleCredentialProvider; @@ -520,10 +521,13 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide * @param context The context object for the turn. * @param connectionName The name of the auth connection to use. * @param magicCode Optional. The validation code the user entered. + * @param oAuthAppCredentials AppCredentials for OAuth. * * @returns A [TokenResponse](xref:botframework-schema.TokenResponse) object that contains the user token. */ - public async getUserToken(context: TurnContext, connectionName: string, magicCode?: string): Promise { + public async getUserToken(context: TurnContext, connectionName: string, magicCode?: string): Promise; + public async getUserToken(context: TurnContext, connectionName: string, magicCode?: string, oAuthAppCredentials?: AppCredentials): Promise; + public async getUserToken(context: TurnContext, connectionName: string, magicCode?: string, oAuthAppCredentials?: AppCredentials): Promise { if (!context.activity.from || !context.activity.from.id) { throw new Error(`BotFrameworkAdapter.getUserToken(): missing from or from.id`); } @@ -533,7 +537,8 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide this.checkEmulatingOAuthCards(context); const userId: string = context.activity.from.id; const url: string = this.oauthApiUrl(context); - const client: TokenApiClient = this.createTokenApiClient(url); + const client: TokenApiClient = this.createTokenApiClient(url, oAuthAppCredentials); + context.turnState.set(this.TokenApiClientCredentialsKey, client); const result: TokenApiModels.UserTokenGetTokenResponse = await client.userToken.getToken(userId, connectionName, { code: magicCode, channelId: context.activity.channelId }); if (!result || !result.token || result._response.status == 404) { @@ -549,8 +554,11 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide * @param context The context object for the turn. * @param connectionName The name of the auth connection to use. * @param userId The ID of user to sign out. + * @param oAuthAppCredentials AppCredentials for OAuth. */ - public async signOutUser(context: TurnContext, connectionName?: string, userId?: string): Promise { + public async signOutUser(context: TurnContext, connectionName?: string, userId?: string): Promise; + public async signOutUser(context: TurnContext, connectionName?: string, userId?: string, oAuthAppCredentials?: AppCredentials): Promise; + public async signOutUser(context: TurnContext, connectionName?: string, userId?: string, oAuthAppCredentials?: AppCredentials): Promise { if (!context.activity.from || !context.activity.from.id) { throw new Error(`BotFrameworkAdapter.signOutUser(): missing from or from.id`); } @@ -560,7 +568,9 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide this.checkEmulatingOAuthCards(context); const url: string = this.oauthApiUrl(context); - const client: TokenApiClient = this.createTokenApiClient(url); + const client: TokenApiClient = this.createTokenApiClient(url, oAuthAppCredentials); + context.turnState.set(this.TokenApiClientCredentialsKey, client); + await client.userToken.signOut(userId, { connectionName: connectionName, channelId: context.activity.channelId } ); } @@ -570,12 +580,16 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide * * @param context The context object for the turn. * @param connectionName The name of the auth connection to use. + * @param oAuthAppCredentials AppCredentials for OAuth. */ - public async getSignInLink(context: TurnContext, connectionName: string): Promise { + public async getSignInLink(context: TurnContext, connectionName: string): Promise; + public async getSignInLink(context: TurnContext, connectionName: string, oAuthAppCredentials?: AppCredentials): Promise; + public async getSignInLink(context: TurnContext, connectionName: string, oAuthAppCredentials?: AppCredentials): Promise { this.checkEmulatingOAuthCards(context); const conversation: Partial = TurnContext.getConversationReference(context.activity); const url: string = this.oauthApiUrl(context); - const client: TokenApiClient = this.createTokenApiClient(url); + const client: TokenApiClient = this.createTokenApiClient(url, oAuthAppCredentials); + context.turnState.set(this.TokenApiClientCredentialsKey, client); const state: any = { ConnectionName: connectionName, Conversation: conversation, @@ -594,17 +608,21 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide * Otherwise, the ID of the user who sent the current activity is used. * @param includeFilter Optional. A comma-separated list of connection's to include. If present, * the `includeFilter` parameter limits the tokens this method returns. + * @param oAuthAppCredentials AppCredentials for OAuth. * * @returns The [TokenStatus](xref:botframework-connector.TokenStatus) objects retrieved. */ - public async getTokenStatus(context: TurnContext, userId?: string, includeFilter?: string ): Promise { + public async getTokenStatus(context: TurnContext, userId?: string, includeFilter?: string): Promise; + public async getTokenStatus(context: TurnContext, userId?: string, includeFilter?: string, oAuthAppCredentials?: AppCredentials): Promise; + public async getTokenStatus(context: TurnContext, userId?: string, includeFilter?: string, oAuthAppCredentials?: AppCredentials): Promise { if (!userId && (!context.activity.from || !context.activity.from.id)) { throw new Error(`BotFrameworkAdapter.getTokenStatus(): missing from or from.id`); } this.checkEmulatingOAuthCards(context); userId = userId || context.activity.from.id; const url: string = this.oauthApiUrl(context); - const client: TokenApiClient = this.createTokenApiClient(url); + const client: TokenApiClient = this.createTokenApiClient(url, oAuthAppCredentials); + context.turnState.set(this.TokenApiClientCredentialsKey, client); return (await client.userToken.getTokenStatus(userId, {channelId: context.activity.channelId, include: includeFilter}))._response.parsedBody; } @@ -615,19 +633,21 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide * @param context The context object for the turn. * @param connectionName The name of the auth connection to use. * @param resourceUrls The list of resource URLs to retrieve tokens for. + * @param oAuthAppCredentials AppCredentials for OAuth. * * @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[]): 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?: AppCredentials): Promise<{[propertyName: string]: TokenResponse;}> { if (!context.activity.from || !context.activity.from.id) { throw new Error(`BotFrameworkAdapter.getAadTokens(): missing from or from.id`); } this.checkEmulatingOAuthCards(context); const userId: string = context.activity.from.id; const url: string = this.oauthApiUrl(context); - const client: TokenApiClient = this.createTokenApiClient(url); + const client: TokenApiClient = this.createTokenApiClient(url, oAuthAppCredentials); + context.turnState.set(this.TokenApiClientCredentialsKey, client); return (await client.userToken.getAadTokens(userId, connectionName, { resourceUrls: resourceUrls }, { channelId: context.activity.channelId }))._response.parsedBody as {[propertyName: string]: TokenResponse }; } @@ -1013,12 +1033,15 @@ export class BotFrameworkAdapter extends BotAdapter implements IUserTokenProvide * Creates an OAuth API client. * * @param serviceUrl The client's service URL. + * @param oAuthAppCredentials AppCredentials for OAuth. * * @remarks * Override this in a derived class to create a mock OAuth API client for unit testing. */ - protected createTokenApiClient(serviceUrl: string): TokenApiClient { - const client = new TokenApiClient(this.credentials, { baseUri: serviceUrl, userAgent: USER_AGENT }); + protected createTokenApiClient(serviceUrl: string, oAuthAppCredentials: AppCredentials): TokenApiClient { + const tokenApiClientCredentials = oAuthAppCredentials ? oAuthAppCredentials : this.credentials; + const client = new TokenApiClient(tokenApiClientCredentials, { baseUri: serviceUrl, userAgent: USER_AGENT }); + return client; } diff --git a/libraries/botbuilder/src/streaming/tokenResolver.ts b/libraries/botbuilder/src/streaming/tokenResolver.ts index 9db3fce193..7f33d46fd1 100644 --- a/libraries/botbuilder/src/streaming/tokenResolver.ts +++ b/libraries/botbuilder/src/streaming/tokenResolver.ts @@ -55,7 +55,8 @@ export class TokenResolver { private static pollForToken(adapter: BotFrameworkAdapter, context: TurnContext, activity: Activity, connectionName: string, pollingTimeout: Date, log?: string[]) { if (pollingTimeout > new Date()) { - adapter.getUserToken(context, connectionName).then((tokenResponse: TokenResponse) => { + const tokenApiClientCredentials = context.turnState.get(adapter.TokenApiClientCredentialsKey); + adapter.getUserToken(context, connectionName, null, tokenApiClientCredentials).then((tokenResponse: TokenResponse) => { let pollingIntervalMs = TokenResolver.PollingIntervalMs; if (tokenResponse) { if (tokenResponse.token) { diff --git a/libraries/botbuilder/tests/botFrameworkAdapter.test.js b/libraries/botbuilder/tests/botFrameworkAdapter.test.js index 2e48f301e6..8c4ea06222 100644 --- a/libraries/botbuilder/tests/botFrameworkAdapter.test.js +++ b/libraries/botbuilder/tests/botFrameworkAdapter.test.js @@ -903,7 +903,7 @@ describe(`BotFrameworkAdapter`, function () { it(`should throw error if missing from in getUserToken()`, async function () { try { const adapter = new AdapterUnderTest(); - await adapter.getUserToken({ activity: {} }); + await adapter.getUserToken({ activity: {}, turnState: new Map() }); } catch (err) { assert(err.message === 'BotFrameworkAdapter.getUserToken(): missing from or from.id', `expected "BotFrameworkAdapter.getUserToken(): missing from or from.id" Error message, not "${ err.message }"`); @@ -915,7 +915,7 @@ describe(`BotFrameworkAdapter`, function () { it(`should throw error if missing from.id in getUserToken()`, async function () { try { const adapter = new AdapterUnderTest(); - await adapter.getUserToken({ activity: { from: {} } }); + await adapter.getUserToken({ activity: { from: {} }, turnState: new Map() }); } catch (err) { assert(err.message === 'BotFrameworkAdapter.getUserToken(): missing from or from.id', `expected "BotFrameworkAdapter.getUserToken(): missing from or from.id" Error message, not "${ err.message }"`); @@ -927,7 +927,7 @@ describe(`BotFrameworkAdapter`, function () { it(`should throw error if missing connectionName`, async function () { try { const adapter = new AdapterUnderTest(); - await adapter.getUserToken({ activity: { from: {id: 'some id'} } }); + await adapter.getUserToken({ activity: { from: {id: 'some id'} }, turnState: new Map() }); } catch (err) { assert(err.message === 'getUserToken() requires a connectionName but none was provided.', `expected "getUserToken() requires a connectionName but none was provided." Error message, not "${ err.message }"`); @@ -956,7 +956,7 @@ describe(`BotFrameworkAdapter`, function () { connector.TokenApiClient = MockTokenApiClient; const adapter = new AdapterUnderTest(); const token = await adapter.getUserToken( - { activity: { channelId: 'The Facebook', from: {id: 'some id'} } }, + { activity: { channelId: 'The Facebook', from: {id: 'some id'} }, turnState: new Map() }, 'aConnectionName'); assert.ok(JSON.stringify(token) === JSON.stringify({ @@ -979,7 +979,7 @@ describe(`BotFrameworkAdapter`, function () { it(`should throw error if missing from in signOutUser()`, async function () { try { const adapter = new AdapterUnderTest(); - await adapter.signOutUser({ activity: {} }); + await adapter.signOutUser({ activity: {}, turnState: new Map() }); } catch (err) { assert(err.message === 'BotFrameworkAdapter.signOutUser(): missing from or from.id', `expected "BotFrameworkAdapter.signOutUser(): missing from or from.id" Error message, not "${ err.message }"`); @@ -991,7 +991,7 @@ describe(`BotFrameworkAdapter`, function () { it(`should throw error if missing from.id in signOutUser()`, async function () { try { const adapter = new AdapterUnderTest(); - await adapter.signOutUser({ activity: { from: {} } }); + await adapter.signOutUser({ activity: { from: {} }, turnState: new Map() }); } catch (err) { assert(err.message === 'BotFrameworkAdapter.signOutUser(): missing from or from.id', `expected "BotFrameworkAdapter.signOutUser(): missing from or from.id" Error message, not "${ err.message }"`); @@ -1003,7 +1003,7 @@ describe(`BotFrameworkAdapter`, function () { it(`should throw error if missing from in getAadTokens()`, async function () { try { const adapter = new AdapterUnderTest(); - await adapter.getAadTokens({ activity: {} }); + await adapter.getAadTokens({ activity: {}, turnState: new Map() }); } catch (err) { assert(err.message === 'BotFrameworkAdapter.getAadTokens(): missing from or from.id', `expected "BotFrameworkAdapter.getAadTokens(): missing from or from.id" Error message, not "${ err.message }"`); @@ -1015,7 +1015,7 @@ describe(`BotFrameworkAdapter`, function () { it(`should throw error if missing from.id in getAadTokens()`, async function () { try { const adapter = new AdapterUnderTest(); - await adapter.getAadTokens({ activity: { from: {} } }); + await adapter.getAadTokens({ activity: { from: {} }, turnState: new Map() }); } catch (err) { assert(err.message === 'BotFrameworkAdapter.getAadTokens(): missing from or from.id', `expected "BotFrameworkAdapter.getAadTokens(): missing from or from.id" Error message, not "${ err.message }"`); @@ -1036,7 +1036,7 @@ describe(`BotFrameworkAdapter`, function () { try { const adapter = new AdapterUnderTest(); - await adapter.getTokenStatus({ activity: {} }); + await adapter.getTokenStatus({ activity: {}, turnState: new Map() }); } catch (err) { assert(err.message === 'BotFrameworkAdapter.getTokenStatus(): missing from or from.id', `expected "BotFrameworkAdapter.getTokenStatus(): missing from or from.id" Error message, not "${ err.message }"`); @@ -1048,7 +1048,7 @@ describe(`BotFrameworkAdapter`, function () { it(`should throw error if missing from.id in getTokenStatus()`, async function () { try { const adapter = new AdapterUnderTest(); - await adapter.getTokenStatus({ activity: { from: {} } }); + await adapter.getTokenStatus({ activity: { from: {} }, turnState: new Map() }); } catch (err) { assert(err.message === 'BotFrameworkAdapter.getTokenStatus(): missing from or from.id', `expected "BotFrameworkAdapter.getTokenStatus(): missing from or from.id" Error message, not "${ err.message }"`); diff --git a/libraries/botbuilder/tests/streaming/tokenResolver.test.js b/libraries/botbuilder/tests/streaming/tokenResolver.test.js index 2f475cbfa3..43f507731d 100644 --- a/libraries/botbuilder/tests/streaming/tokenResolver.test.js +++ b/libraries/botbuilder/tests/streaming/tokenResolver.test.js @@ -16,7 +16,7 @@ class MockAdapter extends BotFrameworkAdapter { return context; } - getUserToken(context, connectionName, magicCode) { + getUserToken(context, connectionName, magicCode, oAuthAppCredentials) { return Promise.resolve(this.getUserTokenCallback()); } }