Skip to content

Commit

Permalink
port: skills without app ID and password (#2909)
Browse files Browse the repository at this point in the history
* Properly use RoleTypes

* Add skill roletype, cast to bandaid compiler bug?

* Port anonymous skill changes

* ChannelServiceHandler test

* AppCredentials tests

* SkillsValidation tests

* Fix ClaimsIdentity constructor

* Add comment describing `isAuthenticated` override

* Stgum/q fixes (#2932)

* [PORT] DialogContextMemoryScope (#2895)

* added DialogContextMemoryScope

* removed setMemory implementation in dialog context memory scope

Co-authored-by: Josh Gummersall <[email protected]>
Co-authored-by: Steven Gum <[email protected]>

* exclude browser*.js from bf-connector .nycrc
* other minor cleanup in bf-connector

* Change vmImage to ubuntu for all JS pipelines (#2931)

* Switch to ubuntu vmimage

* Tweak sed commands

* Add ubuntu to the other builds

* Add var NoPublish

* Fix NoPublish logic

* Rename var to DoNotPublishPackages

* Remove DoNotPublishPackages functionality. Instead we limit automatic releases to main branch.

* Fix Package Names task

Co-authored-by: Steven Gum <[email protected]>

Co-authored-by: Zichuan Ma <[email protected]>
Co-authored-by: Josh Gummersall <[email protected]>
Co-authored-by: BruceHaley <[email protected]>

* Fix skill validation tests

* Fix assert message

* Fix test label

* Add extra assertions

Co-authored-by: Steven Gum <[email protected]>
Co-authored-by: Zichuan Ma <[email protected]>
Co-authored-by: BruceHaley <[email protected]>
  • Loading branch information
4 people authored Oct 21, 2020
1 parent d0260ea commit 535e4c4
Show file tree
Hide file tree
Showing 18 changed files with 923 additions and 501 deletions.
3 changes: 2 additions & 1 deletion libraries/botbuilder-core/src/transcriptLogger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
ActivityTypes,
ConversationReference,
ResourceResponse,
RoleTypes,
} from 'botframework-schema';
import { Middleware } from './middlewareSet';
import { TurnContext } from './turnContext';
Expand Down Expand Up @@ -45,7 +46,7 @@ export class TranscriptLoggerMiddleware implements Middleware {
// log incoming activity at beginning of turn
if (context.activity) {
if (!context.activity.from.role) {
context.activity.from.role = 'user';
context.activity.from.role = RoleTypes.User;
}

this.logActivity(transcript, this.cloneActivity(context.activity));
Expand Down
52 changes: 12 additions & 40 deletions libraries/botbuilder/src/botFrameworkHttpClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import axios from 'axios';
import { Activity, BotFrameworkClient, InvokeResponse } from 'botbuilder-core';
import { Activity, BotFrameworkClient, ChannelAccount, InvokeResponse, RoleTypes } from 'botbuilder-core';
import {
AuthenticationConstants,
AppCredentials,
Expand Down Expand Up @@ -58,33 +58,6 @@ export class BotFrameworkHttpClient implements BotFrameworkClient {
* @param conversationId A conversation ID to use for the conversation with the skill.
* @param activity Activity to forward.
*/
public async postActivity<T>(
fromBotId: string,
toBotId: string,
toUrl: string,
serviceUrl: string,
conversationId: string,
activity: Activity
): Promise<InvokeResponse<T>>;
public async postActivity(
fromBotId: string,
toBotId: string,
toUrl: string,
serviceUrl: string,
conversationId: string,
activity: Activity
): Promise<InvokeResponse>;
/**
* Forwards an activity to another bot.
* @template T The type of body in the [InvokeResponse](xref:botbuilder-core.InvokeResponse).
* @param fromBotId The MicrosoftAppId of the bot sending the activity.
* @param toBotId The MicrosoftAppId of the bot receiving the activity.
* @param toUrl The URL of the bot receiving the activity.
* @param serviceUrl The callback Url for the skill host.
* @param conversationId A conversation ID to use for the conversation with the skill.
* @param activity [Activity](xref:botframework-schema.Activity) to forward.
* @returns A `Promise` representing the [InvokeResponse](xref:botbuilder-core.InvokeResponse) for the operation.
*/
public async postActivity<T = any>(
fromBotId: string,
toBotId: string,
Expand Down Expand Up @@ -117,6 +90,7 @@ export class BotFrameworkHttpClient implements BotFrameworkClient {
const originalServiceUrl = activity.serviceUrl;
const originalRelatesTo = activity.relatesTo;
const originalRecipient = activity.recipient;

try {
activity.relatesTo = {
serviceUrl: activity.serviceUrl,
Expand All @@ -139,10 +113,11 @@ export class BotFrameworkHttpClient implements BotFrameworkClient {

// Fixes: https://github.com/microsoft/botframework-sdk/issues/5785
if (!activity.recipient) {
activity.recipient = {} as any;
activity.recipient = {} as ChannelAccount;
}
activity.recipient.role = RoleTypes.Skill;

const config = {
const config: { headers: Record<string, string>; validateStatus: () => boolean } = {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Expand All @@ -152,13 +127,11 @@ export class BotFrameworkHttpClient implements BotFrameworkClient {
};

if (token) {
config.headers['Authorization'] = `Bearer ${token}`;
config.headers.Authorization = `Bearer ${token}`;
}

const response = await axios.post(toUrl, activity, config);
const invokeResponse: InvokeResponse<T> = { status: response.status, body: response.data };

return invokeResponse;
const response = await axios.post<T>(toUrl, activity, config);
return { status: response.status, body: response.data };
} finally {
// Restore activity properties.
activity.conversation.id = originalConversationId;
Expand All @@ -177,14 +150,13 @@ export class BotFrameworkHttpClient implements BotFrameworkClient {
*/
protected async buildCredentials(appId: string, oAuthScope?: string): Promise<AppCredentials> {
const appPassword = await this.credentialProvider.getAppPassword(appId);
let appCredentials;
if (JwtTokenValidation.isGovernment(this.channelService)) {
appCredentials = new MicrosoftAppCredentials(appId, appPassword, undefined, oAuthScope);
const appCredentials = new MicrosoftAppCredentials(appId, appPassword, undefined, oAuthScope);
appCredentials.oAuthEndpoint = GovernmentConstants.ToChannelFromBotLoginUrl;
return appCredentials;
} else {
appCredentials = new MicrosoftAppCredentials(appId, appPassword, undefined, oAuthScope);
return new MicrosoftAppCredentials(appId, appPassword, undefined, oAuthScope);
}
return appCredentials;
}

/**
Expand All @@ -206,7 +178,7 @@ export class BotFrameworkHttpClient implements BotFrameworkClient {
}

// Credentials not found in cache, build them
appCredentials = (await this.buildCredentials(appId, oAuthScope)) as MicrosoftAppCredentials;
appCredentials = await this.buildCredentials(appId, oAuthScope);

// Cache the credentials for later use
BotFrameworkHttpClient.appCredentialMapCache.set(cacheKey, appCredentials);
Expand Down
38 changes: 19 additions & 19 deletions libraries/botbuilder/src/channelServiceHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
ClaimsIdentity,
ICredentialProvider,
JwtTokenValidation,
SkillValidation,
} from 'botframework-connector';
import { StatusCodeError } from './statusCodeError';

Expand Down Expand Up @@ -597,27 +598,26 @@ export class ChannelServiceHandler {
* @private
*/
private async authenticate(authHeader: string): Promise<ClaimsIdentity> {
try {
if (!authHeader) {
const isAuthDisable = this.credentialProvider.isAuthenticationDisabled();
if (isAuthDisable) {
// In the scenario where Auth is disabled, we still want to have the
// IsAuthenticated flag set in the ClaimsIdentity. To do this requires
// adding in an empty claim.
return new ClaimsIdentity([], false);
}
if (!authHeader) {
const isAuthDisabled = await this.credentialProvider.isAuthenticationDisabled();
if (!isAuthDisabled) {
throw new StatusCodeError(StatusCodes.UNAUTHORIZED);
}

return await JwtTokenValidation.validateAuthHeader(
authHeader,
this.credentialProvider,
this.channelService,
'unknown',
undefined,
this.authConfig
);
} catch (err) {
throw new StatusCodeError(StatusCodes.UNAUTHORIZED);
// In the scenario where Auth is disabled, we still want to have the
// IsAuthenticated flag set in the ClaimsIdentity. To do this requires
// adding in an empty claim.
// Since ChannelServiceHandler calls are always a skill callback call, we set the skill claim too.
return SkillValidation.createAnonymousSkillClaim();
}

return JwtTokenValidation.validateAuthHeader(
authHeader,
this.credentialProvider,
this.channelService,
'unknown',
undefined,
this.authConfig
);
}
}
22 changes: 11 additions & 11 deletions libraries/botbuilder/src/eventFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ export class EventFactory {
* @param handoffContext Agent hub-specific context.
* @param transcript Transcript of the conversation.
*/
public static createHandoffInitiation(
public static createHandoffInitiation<T = unknown>(
context: TurnContext,
handoffContext: any,
handoffContext: T,
transcript?: Transcript
): Activity {
if (!context) {
Expand All @@ -30,7 +30,7 @@ export class EventFactory {
const handoffEvent = this.createHandoffEvent(
HandoffEventNames.InitiateHandoff,
handoffContext,
context.activity.conversation
context.activity.conversation as ConversationAccount // TODO(joshgummersall) why is this necessary?
);

handoffEvent.from = context.activity.from;
Expand Down Expand Up @@ -66,18 +66,18 @@ export class EventFactory {
throw new TypeError('EventFactory.createHandoffStatus(): missing state.');
}

const value: any = { state, message };

const handoffEvent = this.createHandoffEvent(HandoffEventNames.HandoffStatus, value, conversation);

return handoffEvent;
return this.createHandoffEvent(HandoffEventNames.HandoffStatus, { state, message }, conversation);
}

/**
* @private
*/
private static createHandoffEvent(name: string, value: any, conversation: ConversationAccount): Activity {
const handoffEvent: Activity = {} as any;
private static createHandoffEvent<T = unknown>(
name: string,
value: T,
conversation: ConversationAccount
): Activity {
const handoffEvent: Partial<Activity> = {};

handoffEvent.name = name;
handoffEvent.value = value;
Expand All @@ -90,7 +90,7 @@ export class EventFactory {
handoffEvent.attachments = [];
handoffEvent.entities = [];

return handoffEvent;
return handoffEvent as Activity;
}
}

Expand Down
Loading

0 comments on commit 535e4c4

Please sign in to comment.