@microsoft/teamsfx 0.3.3-alpha.3dc53ce2.0 → 0.3.3-alpha.7e7c7c23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/index.esm2017.js +1413 -0
- package/dist/index.esm2017.js.map +1 -0
- package/dist/{index.js → index.esm2017.mjs} +1467 -1506
- package/dist/index.esm2017.mjs.map +1 -0
- package/dist/index.esm5.js +1575 -0
- package/dist/index.esm5.js.map +1 -0
- package/dist/index.node.cjs.js +1653 -0
- package/dist/index.node.cjs.js.map +1 -0
- package/package.json +58 -78
- package/types/teamsfx.d.ts +0 -2
- package/dist/index.js.map +0 -1
- package/dist/teamsfx.js +0 -30
- package/dist/teamsfx.js.map +0 -1
- package/dist-esm/src/bot/teamsBotSsoPrompt.browser.js +0 -118
- package/dist-esm/src/bot/teamsBotSsoPrompt.browser.js.map +0 -1
- package/dist-esm/src/bot/teamsBotSsoPrompt.js +0 -349
- package/dist-esm/src/bot/teamsBotSsoPrompt.js.map +0 -1
- package/dist-esm/src/bot/teamsBotSsoPromptTokenResponse.js +0 -2
- package/dist-esm/src/bot/teamsBotSsoPromptTokenResponse.js.map +0 -1
- package/dist-esm/src/core/cache.browser.js +0 -22
- package/dist-esm/src/core/cache.browser.js.map +0 -1
- package/dist-esm/src/core/cache.js +0 -28
- package/dist-esm/src/core/cache.js.map +0 -1
- package/dist-esm/src/core/configurationProvider.js +0 -124
- package/dist-esm/src/core/configurationProvider.js.map +0 -1
- package/dist-esm/src/core/defaultTediousConnectionConfiguration.browser.js +0 -28
- package/dist-esm/src/core/defaultTediousConnectionConfiguration.browser.js.map +0 -1
- package/dist-esm/src/core/defaultTediousConnectionConfiguration.js +0 -182
- package/dist-esm/src/core/defaultTediousConnectionConfiguration.js.map +0 -1
- package/dist-esm/src/core/errors.js +0 -97
- package/dist-esm/src/core/errors.js.map +0 -1
- package/dist-esm/src/core/msGraphAuthProvider.js +0 -68
- package/dist-esm/src/core/msGraphAuthProvider.js.map +0 -1
- package/dist-esm/src/core/msGraphClientProvider.js +0 -65
- package/dist-esm/src/core/msGraphClientProvider.js.map +0 -1
- package/dist-esm/src/credential/m365TenantCredential.browser.js +0 -38
- package/dist-esm/src/credential/m365TenantCredential.browser.js.map +0 -1
- package/dist-esm/src/credential/m365TenantCredential.js +0 -126
- package/dist-esm/src/credential/m365TenantCredential.js.map +0 -1
- package/dist-esm/src/credential/onBehalfOfUserCredential.browser.js +0 -46
- package/dist-esm/src/credential/onBehalfOfUserCredential.browser.js.map +0 -1
- package/dist-esm/src/credential/onBehalfOfUserCredential.js +0 -178
- package/dist-esm/src/credential/onBehalfOfUserCredential.js.map +0 -1
- package/dist-esm/src/credential/teamsUserCredential.browser.js +0 -462
- package/dist-esm/src/credential/teamsUserCredential.browser.js.map +0 -1
- package/dist-esm/src/credential/teamsUserCredential.js +0 -56
- package/dist-esm/src/credential/teamsUserCredential.js.map +0 -1
- package/dist-esm/src/index.js +0 -14
- package/dist-esm/src/index.js.map +0 -1
- package/dist-esm/src/models/accessTokenResult.js +0 -4
- package/dist-esm/src/models/accessTokenResult.js.map +0 -1
- package/dist-esm/src/models/authCodeResult.js +0 -4
- package/dist-esm/src/models/authCodeResult.js.map +0 -1
- package/dist-esm/src/models/configuration.js +0 -20
- package/dist-esm/src/models/configuration.js.map +0 -1
- package/dist-esm/src/models/grantType.js +0 -11
- package/dist-esm/src/models/grantType.js.map +0 -1
- package/dist-esm/src/models/ssoTokenInfo.js +0 -4
- package/dist-esm/src/models/ssoTokenInfo.js.map +0 -1
- package/dist-esm/src/models/userinfo.js +0 -4
- package/dist-esm/src/models/userinfo.js.map +0 -1
- package/dist-esm/src/util/logger.js +0 -134
- package/dist-esm/src/util/logger.js.map +0 -1
- package/dist-esm/src/util/utils.js +0 -130
- package/dist-esm/src/util/utils.js.map +0 -1
- package/dist-esm/src/util/utils.node.js +0 -23
- package/dist-esm/src/util/utils.node.js.map +0 -1
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT license.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
|
-
import { ErrorWithCode, ErrorCode, ErrorMessage } from "../core/errors";
|
|
5
|
-
import { formatString } from "../util/utils";
|
|
6
|
-
/**
|
|
7
|
-
* Creates a new prompt that leverage Teams Single Sign On (SSO) support for bot to automatically sign in user and
|
|
8
|
-
* help receive oauth token, asks the user to consent if needed.
|
|
9
|
-
*
|
|
10
|
-
* @remarks
|
|
11
|
-
* The prompt will attempt to retrieve the users current token of the desired scopes and store it in
|
|
12
|
-
* the token store.
|
|
13
|
-
*
|
|
14
|
-
* User will be automatically signed in leveraging Teams support of Bot Single Sign On(SSO):
|
|
15
|
-
* https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/auth-aad-sso-bots
|
|
16
|
-
*
|
|
17
|
-
* @example
|
|
18
|
-
* When used with your bots `DialogSet` you can simply add a new instance of the prompt as a named
|
|
19
|
-
* dialog using `DialogSet.add()`. You can then start the prompt from a waterfall step using either
|
|
20
|
-
* `DialogContext.beginDialog()` or `DialogContext.prompt()`. The user will be prompted to sign in as
|
|
21
|
-
* needed and their access token will be passed as an argument to the callers next waterfall step:
|
|
22
|
-
*
|
|
23
|
-
* ```JavaScript
|
|
24
|
-
* const { ConversationState, MemoryStorage } = require('botbuilder');
|
|
25
|
-
* const { DialogSet, WaterfallDialog } = require('botbuilder-dialogs');
|
|
26
|
-
* const { TeamsBotSsoPrompt } = require('@microsoft/teamsfx');
|
|
27
|
-
*
|
|
28
|
-
* const convoState = new ConversationState(new MemoryStorage());
|
|
29
|
-
* const dialogState = convoState.createProperty('dialogState');
|
|
30
|
-
* const dialogs = new DialogSet(dialogState);
|
|
31
|
-
*
|
|
32
|
-
* loadConfiguration();
|
|
33
|
-
* dialogs.add(new TeamsBotSsoPrompt('TeamsBotSsoPrompt', {
|
|
34
|
-
* scopes: ["User.Read"],
|
|
35
|
-
* }));
|
|
36
|
-
*
|
|
37
|
-
* dialogs.add(new WaterfallDialog('taskNeedingLogin', [
|
|
38
|
-
* async (step) => {
|
|
39
|
-
* return await step.beginDialog('TeamsBotSsoPrompt');
|
|
40
|
-
* },
|
|
41
|
-
* async (step) => {
|
|
42
|
-
* const token = step.result;
|
|
43
|
-
* if (token) {
|
|
44
|
-
*
|
|
45
|
-
* // ... continue with task needing access token ...
|
|
46
|
-
*
|
|
47
|
-
* } else {
|
|
48
|
-
* await step.context.sendActivity(`Sorry... We couldn't log you in. Try again later.`);
|
|
49
|
-
* return await step.endDialog();
|
|
50
|
-
* }
|
|
51
|
-
* }
|
|
52
|
-
* ]));
|
|
53
|
-
* ```
|
|
54
|
-
*
|
|
55
|
-
* @beta
|
|
56
|
-
*/
|
|
57
|
-
export class TeamsBotSsoPrompt {
|
|
58
|
-
/**
|
|
59
|
-
* Constructor of TeamsBotSsoPrompt.
|
|
60
|
-
*
|
|
61
|
-
* @param dialogId Unique ID of the dialog within its parent `DialogSet` or `ComponentDialog`.
|
|
62
|
-
* @param settings Settings used to configure the prompt.
|
|
63
|
-
*
|
|
64
|
-
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
65
|
-
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
66
|
-
*
|
|
67
|
-
* @beta
|
|
68
|
-
*/
|
|
69
|
-
constructor(dialogId, settings) {
|
|
70
|
-
this.settings = settings;
|
|
71
|
-
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "TeamsBotSsoPrompt"), ErrorCode.RuntimeNotSupported);
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Called when a prompt dialog is pushed onto the dialog stack and is being activated.
|
|
75
|
-
* @remarks
|
|
76
|
-
* If the task is successful, the result indicates whether the prompt is still
|
|
77
|
-
* active after the turn has been processed by the prompt.
|
|
78
|
-
*
|
|
79
|
-
* @param dc The DialogContext for the current turn of the conversation.
|
|
80
|
-
*
|
|
81
|
-
* @throws {@link ErrorCode|InvalidParameter} when timeout property in teams bot sso prompt settings is not number or is not positive.
|
|
82
|
-
* @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.
|
|
83
|
-
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
84
|
-
*
|
|
85
|
-
* @returns A `Promise` representing the asynchronous operation.
|
|
86
|
-
*
|
|
87
|
-
* @beta
|
|
88
|
-
*/
|
|
89
|
-
beginDialog(dc) {
|
|
90
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
-
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "TeamsBotSsoPrompt"), ErrorCode.RuntimeNotSupported);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Called when a prompt dialog is the active dialog and the user replied with a new activity.
|
|
96
|
-
*
|
|
97
|
-
* @remarks
|
|
98
|
-
* If the task is successful, the result indicates whether the dialog is still
|
|
99
|
-
* active after the turn has been processed by the dialog.
|
|
100
|
-
* The prompt generally continues to receive the user's replies until it accepts the
|
|
101
|
-
* user's reply as valid input for the prompt.
|
|
102
|
-
*
|
|
103
|
-
* @param dc The DialogContext for the current turn of the conversation.
|
|
104
|
-
*
|
|
105
|
-
* @returns A `Promise` representing the asynchronous operation.
|
|
106
|
-
*
|
|
107
|
-
* @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.
|
|
108
|
-
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
109
|
-
*
|
|
110
|
-
* @beta
|
|
111
|
-
*/
|
|
112
|
-
continueDialog(dc) {
|
|
113
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
114
|
-
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "TeamsBotSsoPrompt"), ErrorCode.RuntimeNotSupported);
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
//# sourceMappingURL=teamsBotSsoPrompt.browser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"teamsBotSsoPrompt.browser.js","sourceRoot":"","sources":["../../../src/bot/teamsBotSsoPrompt.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;;AAGlC,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AA+B7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,MAAM,OAAO,iBAAiB;IAC5B;;;;;;;;;;OAUG;IACH,YAAY,QAAgB,EAAU,QAAmC;QAAnC,aAAQ,GAAR,QAAQ,CAA2B;QACvE,MAAM,IAAI,aAAa,CACrB,YAAY,CAAC,YAAY,CAAC,0BAA0B,EAAE,mBAAmB,CAAC,EAC1E,SAAS,CAAC,mBAAmB,CAC9B,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACU,WAAW,CAAC,EAAiB;;YACxC,MAAM,IAAI,aAAa,CACrB,YAAY,CAAC,YAAY,CAAC,0BAA0B,EAAE,mBAAmB,CAAC,EAC1E,SAAS,CAAC,mBAAmB,CAC9B,CAAC;QACJ,CAAC;KAAA;IAED;;;;;;;;;;;;;;;;;OAiBG;IACU,cAAc,CAAC,EAAiB;;YAC3C,MAAM,IAAI,aAAa,CACrB,YAAY,CAAC,YAAY,CAAC,0BAA0B,EAAE,mBAAmB,CAAC,EAC1E,SAAS,CAAC,mBAAmB,CAC9B,CAAC;QACJ,CAAC;KAAA;CACF","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { DialogContext, DialogTurnResult } from \"botbuilder-dialogs\";\nimport { ErrorWithCode, ErrorCode, ErrorMessage } from \"../core/errors\";\nimport { formatString } from \"../util/utils\";\n\n/**\n * Settings used to configure an TeamsBotSsoPrompt instance.\n *\n * @remarks\n * Only works in in server side.\n *\n * @beta\n */\nexport interface TeamsBotSsoPromptSettings {\n /**\n * The array of strings that declare the desired permissions and the resources requested.\n */\n scopes: string[];\n\n /**\n * (Optional) number of milliseconds the prompt will wait for the user to authenticate.\n * Defaults to a value `900,000` (15 minutes.)\n */\n timeout?: number;\n\n /**\n * (Optional) value indicating whether the TeamsBotSsoPrompt should end upon receiving an\n * invalid message. Generally the TeamsBotSsoPrompt will end the auth flow when receives user\n * message not related to the auth flow. Setting the flag to false ignores the user's message instead.\n * Defaults to value `true`\n */\n endOnInvalidMessage?: boolean;\n}\n\n/**\n * Creates a new prompt that leverage Teams Single Sign On (SSO) support for bot to automatically sign in user and\n * help receive oauth token, asks the user to consent if needed.\n *\n * @remarks\n * The prompt will attempt to retrieve the users current token of the desired scopes and store it in\n * the token store.\n *\n * User will be automatically signed in leveraging Teams support of Bot Single Sign On(SSO):\n * https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/auth-aad-sso-bots\n *\n * @example\n * When used with your bots `DialogSet` you can simply add a new instance of the prompt as a named\n * dialog using `DialogSet.add()`. You can then start the prompt from a waterfall step using either\n * `DialogContext.beginDialog()` or `DialogContext.prompt()`. The user will be prompted to sign in as\n * needed and their access token will be passed as an argument to the callers next waterfall step:\n *\n * ```JavaScript\n * const { ConversationState, MemoryStorage } = require('botbuilder');\n * const { DialogSet, WaterfallDialog } = require('botbuilder-dialogs');\n * const { TeamsBotSsoPrompt } = require('@microsoft/teamsfx');\n *\n * const convoState = new ConversationState(new MemoryStorage());\n * const dialogState = convoState.createProperty('dialogState');\n * const dialogs = new DialogSet(dialogState);\n *\n * loadConfiguration();\n * dialogs.add(new TeamsBotSsoPrompt('TeamsBotSsoPrompt', {\n * scopes: [\"User.Read\"],\n * }));\n *\n * dialogs.add(new WaterfallDialog('taskNeedingLogin', [\n * async (step) => {\n * return await step.beginDialog('TeamsBotSsoPrompt');\n * },\n * async (step) => {\n * const token = step.result;\n * if (token) {\n *\n * // ... continue with task needing access token ...\n *\n * } else {\n * await step.context.sendActivity(`Sorry... We couldn't log you in. Try again later.`);\n * return await step.endDialog();\n * }\n * }\n * ]));\n * ```\n *\n * @beta\n */\nexport class TeamsBotSsoPrompt {\n /**\n * Constructor of TeamsBotSsoPrompt.\n *\n * @param dialogId Unique ID of the dialog within its parent `DialogSet` or `ComponentDialog`.\n * @param settings Settings used to configure the prompt.\n *\n * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.\n * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.\n *\n * @beta\n */\n constructor(dialogId: string, private settings: TeamsBotSsoPromptSettings) {\n throw new ErrorWithCode(\n formatString(ErrorMessage.BrowserRuntimeNotSupported, \"TeamsBotSsoPrompt\"),\n ErrorCode.RuntimeNotSupported\n );\n }\n\n /**\n * Called when a prompt dialog is pushed onto the dialog stack and is being activated.\n * @remarks\n * If the task is successful, the result indicates whether the prompt is still\n * active after the turn has been processed by the prompt.\n *\n * @param dc The DialogContext for the current turn of the conversation.\n *\n * @throws {@link ErrorCode|InvalidParameter} when timeout property in teams bot sso prompt settings is not number or is not positive.\n * @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.\n * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.\n *\n * @returns A `Promise` representing the asynchronous operation.\n *\n * @beta\n */\n public async beginDialog(dc: DialogContext): Promise<DialogTurnResult> {\n throw new ErrorWithCode(\n formatString(ErrorMessage.BrowserRuntimeNotSupported, \"TeamsBotSsoPrompt\"),\n ErrorCode.RuntimeNotSupported\n );\n }\n\n /**\n * Called when a prompt dialog is the active dialog and the user replied with a new activity.\n *\n * @remarks\n * If the task is successful, the result indicates whether the dialog is still\n * active after the turn has been processed by the dialog.\n * The prompt generally continues to receive the user's replies until it accepts the\n * user's reply as valid input for the prompt.\n *\n * @param dc The DialogContext for the current turn of the conversation.\n *\n * @returns A `Promise` representing the asynchronous operation.\n *\n * @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.\n * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.\n *\n * @beta\n */\n public async continueDialog(dc: DialogContext): Promise<DialogTurnResult> {\n throw new ErrorWithCode(\n formatString(ErrorMessage.BrowserRuntimeNotSupported, \"TeamsBotSsoPrompt\"),\n ErrorCode.RuntimeNotSupported\n );\n }\n}\n"]}
|
|
@@ -1,349 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT license.
|
|
3
|
-
import { __awaiter } from "tslib";
|
|
4
|
-
import { ActivityTypes, CardFactory, Channels, MessageFactory, ActionTypes, verifyStateOperationName, StatusCodes, tokenExchangeOperationName, TeamsInfo, } from "botbuilder";
|
|
5
|
-
import { Dialog, } from "botbuilder-dialogs";
|
|
6
|
-
import { config } from "../core/configurationProvider";
|
|
7
|
-
import { OnBehalfOfUserCredential } from "../credential/onBehalfOfUserCredential";
|
|
8
|
-
import { v4 as uuidv4 } from "uuid";
|
|
9
|
-
import { ErrorWithCode, ErrorCode, ErrorMessage } from "../core/errors";
|
|
10
|
-
import { internalLogger } from "../util/logger";
|
|
11
|
-
import { validateScopesType, formatString, parseJwt } from "../util/utils";
|
|
12
|
-
const invokeResponseType = "invokeResponse";
|
|
13
|
-
/**
|
|
14
|
-
* Response body returned for a token exchange invoke activity.
|
|
15
|
-
*
|
|
16
|
-
* @beta
|
|
17
|
-
*/
|
|
18
|
-
class TokenExchangeInvokeResponse {
|
|
19
|
-
constructor(id, failureDetail) {
|
|
20
|
-
this.id = id;
|
|
21
|
-
this.failureDetail = failureDetail;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Creates a new prompt that leverage Teams Single Sign On (SSO) support for bot to automatically sign in user and
|
|
26
|
-
* help receive oauth token, asks the user to consent if needed.
|
|
27
|
-
*
|
|
28
|
-
* @remarks
|
|
29
|
-
* The prompt will attempt to retrieve the users current token of the desired scopes and store it in
|
|
30
|
-
* the token store.
|
|
31
|
-
*
|
|
32
|
-
* User will be automatically signed in leveraging Teams support of Bot Single Sign On(SSO):
|
|
33
|
-
* https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/auth-aad-sso-bots
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* When used with your bots `DialogSet` you can simply add a new instance of the prompt as a named
|
|
37
|
-
* dialog using `DialogSet.add()`. You can then start the prompt from a waterfall step using either
|
|
38
|
-
* `DialogContext.beginDialog()` or `DialogContext.prompt()`. The user will be prompted to sign in as
|
|
39
|
-
* needed and their access token will be passed as an argument to the callers next waterfall step:
|
|
40
|
-
*
|
|
41
|
-
* ```JavaScript
|
|
42
|
-
* const { ConversationState, MemoryStorage } = require('botbuilder');
|
|
43
|
-
* const { DialogSet, WaterfallDialog } = require('botbuilder-dialogs');
|
|
44
|
-
* const { TeamsBotSsoPrompt } = require('@microsoft/teamsfx');
|
|
45
|
-
*
|
|
46
|
-
* const convoState = new ConversationState(new MemoryStorage());
|
|
47
|
-
* const dialogState = convoState.createProperty('dialogState');
|
|
48
|
-
* const dialogs = new DialogSet(dialogState);
|
|
49
|
-
*
|
|
50
|
-
* loadConfiguration();
|
|
51
|
-
* dialogs.add(new TeamsBotSsoPrompt('TeamsBotSsoPrompt', {
|
|
52
|
-
* scopes: ["User.Read"],
|
|
53
|
-
* }));
|
|
54
|
-
*
|
|
55
|
-
* dialogs.add(new WaterfallDialog('taskNeedingLogin', [
|
|
56
|
-
* async (step) => {
|
|
57
|
-
* return await step.beginDialog('TeamsBotSsoPrompt');
|
|
58
|
-
* },
|
|
59
|
-
* async (step) => {
|
|
60
|
-
* const token = step.result;
|
|
61
|
-
* if (token) {
|
|
62
|
-
*
|
|
63
|
-
* // ... continue with task needing access token ...
|
|
64
|
-
*
|
|
65
|
-
* } else {
|
|
66
|
-
* await step.context.sendActivity(`Sorry... We couldn't log you in. Try again later.`);
|
|
67
|
-
* return await step.endDialog();
|
|
68
|
-
* }
|
|
69
|
-
* }
|
|
70
|
-
* ]));
|
|
71
|
-
* ```
|
|
72
|
-
*
|
|
73
|
-
* @beta
|
|
74
|
-
*/
|
|
75
|
-
export class TeamsBotSsoPrompt extends Dialog {
|
|
76
|
-
/**
|
|
77
|
-
* Constructor of TeamsBotSsoPrompt.
|
|
78
|
-
*
|
|
79
|
-
* @param dialogId Unique ID of the dialog within its parent `DialogSet` or `ComponentDialog`.
|
|
80
|
-
* @param settings Settings used to configure the prompt.
|
|
81
|
-
*
|
|
82
|
-
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
83
|
-
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
84
|
-
*
|
|
85
|
-
* @beta
|
|
86
|
-
*/
|
|
87
|
-
constructor(dialogId, settings) {
|
|
88
|
-
super(dialogId);
|
|
89
|
-
this.settings = settings;
|
|
90
|
-
validateScopesType(settings.scopes);
|
|
91
|
-
internalLogger.info("Create a new Teams Bot SSO Prompt");
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Called when a prompt dialog is pushed onto the dialog stack and is being activated.
|
|
95
|
-
* @remarks
|
|
96
|
-
* If the task is successful, the result indicates whether the prompt is still
|
|
97
|
-
* active after the turn has been processed by the prompt.
|
|
98
|
-
*
|
|
99
|
-
* @param dc The DialogContext for the current turn of the conversation.
|
|
100
|
-
*
|
|
101
|
-
* @throws {@link ErrorCode|InvalidParameter} when timeout property in teams bot sso prompt settings is not number or is not positive.
|
|
102
|
-
* @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.
|
|
103
|
-
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
104
|
-
*
|
|
105
|
-
* @returns A `Promise` representing the asynchronous operation.
|
|
106
|
-
*
|
|
107
|
-
* @beta
|
|
108
|
-
*/
|
|
109
|
-
beginDialog(dc) {
|
|
110
|
-
var _a;
|
|
111
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
112
|
-
internalLogger.info("Begin Teams Bot SSO Prompt");
|
|
113
|
-
this.ensureMsTeamsChannel(dc);
|
|
114
|
-
// Initialize prompt state
|
|
115
|
-
const default_timeout = 900000;
|
|
116
|
-
let timeout = default_timeout;
|
|
117
|
-
if (this.settings.timeout) {
|
|
118
|
-
if (typeof this.settings.timeout != "number") {
|
|
119
|
-
const errorMsg = "type of timeout property in teamsBotSsoPromptSettings should be number.";
|
|
120
|
-
internalLogger.error(errorMsg);
|
|
121
|
-
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);
|
|
122
|
-
}
|
|
123
|
-
if (this.settings.timeout <= 0) {
|
|
124
|
-
const errorMsg = "value of timeout property in teamsBotSsoPromptSettings should be positive.";
|
|
125
|
-
internalLogger.error(errorMsg);
|
|
126
|
-
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);
|
|
127
|
-
}
|
|
128
|
-
timeout = this.settings.timeout;
|
|
129
|
-
}
|
|
130
|
-
if (this.settings.endOnInvalidMessage === undefined) {
|
|
131
|
-
this.settings.endOnInvalidMessage = true;
|
|
132
|
-
}
|
|
133
|
-
const state = (_a = dc.activeDialog) === null || _a === void 0 ? void 0 : _a.state;
|
|
134
|
-
state.state = {};
|
|
135
|
-
state.options = {};
|
|
136
|
-
state.expires = new Date().getTime() + timeout;
|
|
137
|
-
// Send OAuth card to get SSO token
|
|
138
|
-
yield this.sendOAuthCardAsync(dc.context);
|
|
139
|
-
return Dialog.EndOfTurn;
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
/**
|
|
143
|
-
* Called when a prompt dialog is the active dialog and the user replied with a new activity.
|
|
144
|
-
*
|
|
145
|
-
* @remarks
|
|
146
|
-
* If the task is successful, the result indicates whether the dialog is still
|
|
147
|
-
* active after the turn has been processed by the dialog.
|
|
148
|
-
* The prompt generally continues to receive the user's replies until it accepts the
|
|
149
|
-
* user's reply as valid input for the prompt.
|
|
150
|
-
*
|
|
151
|
-
* @param dc The DialogContext for the current turn of the conversation.
|
|
152
|
-
*
|
|
153
|
-
* @returns A `Promise` representing the asynchronous operation.
|
|
154
|
-
*
|
|
155
|
-
* @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.
|
|
156
|
-
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
157
|
-
*
|
|
158
|
-
* @beta
|
|
159
|
-
*/
|
|
160
|
-
continueDialog(dc) {
|
|
161
|
-
var _a;
|
|
162
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
-
internalLogger.info("Continue Teams Bot SSO Prompt");
|
|
164
|
-
this.ensureMsTeamsChannel(dc);
|
|
165
|
-
// Check for timeout
|
|
166
|
-
const state = (_a = dc.activeDialog) === null || _a === void 0 ? void 0 : _a.state;
|
|
167
|
-
const isMessage = dc.context.activity.type === ActivityTypes.Message;
|
|
168
|
-
const isTimeoutActivityType = isMessage ||
|
|
169
|
-
this.isTeamsVerificationInvoke(dc.context) ||
|
|
170
|
-
this.isTokenExchangeRequestInvoke(dc.context);
|
|
171
|
-
// If the incoming Activity is a message, or an Activity Type normally handled by TeamsBotSsoPrompt,
|
|
172
|
-
// check to see if this TeamsBotSsoPrompt Expiration has elapsed, and end the dialog if so.
|
|
173
|
-
const hasTimedOut = isTimeoutActivityType && new Date().getTime() > state.expires;
|
|
174
|
-
if (hasTimedOut) {
|
|
175
|
-
internalLogger.warn("End Teams Bot SSO Prompt due to timeout");
|
|
176
|
-
return yield dc.endDialog(undefined);
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
if (this.isTeamsVerificationInvoke(dc.context) ||
|
|
180
|
-
this.isTokenExchangeRequestInvoke(dc.context)) {
|
|
181
|
-
// Recognize token
|
|
182
|
-
const recognized = yield this.recognizeToken(dc);
|
|
183
|
-
if (recognized.succeeded) {
|
|
184
|
-
return yield dc.endDialog(recognized.value);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
else if (isMessage && this.settings.endOnInvalidMessage) {
|
|
188
|
-
internalLogger.warn("End Teams Bot SSO Prompt due to invalid message");
|
|
189
|
-
return yield dc.endDialog(undefined);
|
|
190
|
-
}
|
|
191
|
-
return Dialog.EndOfTurn;
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
/**
|
|
196
|
-
* Ensure bot is running in MS Teams since TeamsBotSsoPrompt is only supported in MS Teams channel.
|
|
197
|
-
* @param dc dialog context
|
|
198
|
-
* @throws {@link ErrorCode|ChannelNotSupported} if bot channel is not MS Teams
|
|
199
|
-
* @internal
|
|
200
|
-
*/
|
|
201
|
-
ensureMsTeamsChannel(dc) {
|
|
202
|
-
if (dc.context.activity.channelId != Channels.Msteams) {
|
|
203
|
-
const errorMsg = formatString(ErrorMessage.OnlyMSTeamsChannelSupported, "Teams Bot SSO Prompt");
|
|
204
|
-
internalLogger.error(errorMsg);
|
|
205
|
-
throw new ErrorWithCode(errorMsg, ErrorCode.ChannelNotSupported);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Send OAuthCard that tells Teams to obtain an authentication token for the bot application.
|
|
210
|
-
* For details see https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/auth-aad-sso-bots.
|
|
211
|
-
*
|
|
212
|
-
* @internal
|
|
213
|
-
*/
|
|
214
|
-
sendOAuthCardAsync(context) {
|
|
215
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
216
|
-
internalLogger.verbose("Send OAuth card to get SSO token");
|
|
217
|
-
const account = yield TeamsInfo.getMember(context, context.activity.from.id);
|
|
218
|
-
internalLogger.verbose("Get Teams member account user principal name: " + account.userPrincipalName);
|
|
219
|
-
const loginHint = account.userPrincipalName ? account.userPrincipalName : "";
|
|
220
|
-
const signInResource = this.getSignInResource(loginHint);
|
|
221
|
-
const card = CardFactory.oauthCard("", "Teams SSO Sign In", "Sign In", signInResource.signInLink, signInResource.tokenExchangeResource);
|
|
222
|
-
card.content.buttons[0].type = ActionTypes.Signin;
|
|
223
|
-
const msg = MessageFactory.attachment(card);
|
|
224
|
-
// Send prompt
|
|
225
|
-
yield context.sendActivity(msg);
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Get sign in resource.
|
|
230
|
-
*
|
|
231
|
-
* @throws {@link ErrorCode|InvalidConfiguration} if client id, tenant id or initiate login endpoint is not found in config.
|
|
232
|
-
*
|
|
233
|
-
* @internal
|
|
234
|
-
*/
|
|
235
|
-
getSignInResource(loginHint) {
|
|
236
|
-
var _a, _b, _c, _d, _e;
|
|
237
|
-
internalLogger.verbose("Get sign in authentication configuration");
|
|
238
|
-
const missingConfigurations = [];
|
|
239
|
-
if (!((_a = config === null || config === void 0 ? void 0 : config.authentication) === null || _a === void 0 ? void 0 : _a.initiateLoginEndpoint)) {
|
|
240
|
-
missingConfigurations.push("initiateLoginEndpoint");
|
|
241
|
-
}
|
|
242
|
-
if (!((_b = config === null || config === void 0 ? void 0 : config.authentication) === null || _b === void 0 ? void 0 : _b.clientId)) {
|
|
243
|
-
missingConfigurations.push("clientId");
|
|
244
|
-
}
|
|
245
|
-
if (!((_c = config === null || config === void 0 ? void 0 : config.authentication) === null || _c === void 0 ? void 0 : _c.tenantId)) {
|
|
246
|
-
missingConfigurations.push("tenantId");
|
|
247
|
-
}
|
|
248
|
-
if (!((_d = config === null || config === void 0 ? void 0 : config.authentication) === null || _d === void 0 ? void 0 : _d.applicationIdUri)) {
|
|
249
|
-
missingConfigurations.push("applicationIdUri");
|
|
250
|
-
}
|
|
251
|
-
if (missingConfigurations.length != 0) {
|
|
252
|
-
const errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingConfigurations.join(", "), "undefined");
|
|
253
|
-
internalLogger.error(errorMsg);
|
|
254
|
-
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);
|
|
255
|
-
}
|
|
256
|
-
const signInLink = `${config.authentication.initiateLoginEndpoint}?scope=${encodeURI(this.settings.scopes.join(" "))}&clientId=${config.authentication.clientId}&tenantId=${config.authentication.tenantId}&loginHint=${loginHint}`;
|
|
257
|
-
internalLogger.verbose("Sign in link: " + signInLink);
|
|
258
|
-
const tokenExchangeResource = {
|
|
259
|
-
id: uuidv4(),
|
|
260
|
-
uri: ((_e = config.authentication) === null || _e === void 0 ? void 0 : _e.applicationIdUri.replace(/\/$/, "")) + "/access_as_user",
|
|
261
|
-
};
|
|
262
|
-
internalLogger.verbose("Token exchange resource uri: " + tokenExchangeResource.uri);
|
|
263
|
-
return {
|
|
264
|
-
signInLink: signInLink,
|
|
265
|
-
tokenExchangeResource: tokenExchangeResource,
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
/**
|
|
269
|
-
* @internal
|
|
270
|
-
*/
|
|
271
|
-
recognizeToken(dc) {
|
|
272
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
273
|
-
const context = dc.context;
|
|
274
|
-
let tokenResponse;
|
|
275
|
-
if (this.isTokenExchangeRequestInvoke(context)) {
|
|
276
|
-
internalLogger.verbose("Receive token exchange request");
|
|
277
|
-
// Received activity is not a token exchange request
|
|
278
|
-
if (!(context.activity.value && this.isTokenExchangeRequest(context.activity.value))) {
|
|
279
|
-
const warningMsg = "The bot received an InvokeActivity that is missing a TokenExchangeInvokeRequest value. This is required to be sent with the InvokeActivity.";
|
|
280
|
-
internalLogger.warn(warningMsg);
|
|
281
|
-
yield context.sendActivity(this.getTokenExchangeInvokeResponse(StatusCodes.BAD_REQUEST, warningMsg));
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
const ssoToken = context.activity.value.token;
|
|
285
|
-
const credential = new OnBehalfOfUserCredential(ssoToken);
|
|
286
|
-
let exchangedToken;
|
|
287
|
-
try {
|
|
288
|
-
exchangedToken = yield credential.getToken(this.settings.scopes);
|
|
289
|
-
if (exchangedToken) {
|
|
290
|
-
yield context.sendActivity(this.getTokenExchangeInvokeResponse(StatusCodes.OK, "", context.activity.value.id));
|
|
291
|
-
const ssoTokenExpiration = parseJwt(ssoToken).exp;
|
|
292
|
-
tokenResponse = {
|
|
293
|
-
ssoToken: ssoToken,
|
|
294
|
-
ssoTokenExpiration: new Date(ssoTokenExpiration * 1000).toISOString(),
|
|
295
|
-
connectionName: "",
|
|
296
|
-
token: exchangedToken.token,
|
|
297
|
-
expiration: exchangedToken.expiresOnTimestamp.toString(),
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
catch (error) {
|
|
302
|
-
const warningMsg = "The bot is unable to exchange token. Ask for user consent.";
|
|
303
|
-
internalLogger.info(warningMsg);
|
|
304
|
-
yield context.sendActivity(this.getTokenExchangeInvokeResponse(StatusCodes.PRECONDITION_FAILED, warningMsg, context.activity.value.id));
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
else if (this.isTeamsVerificationInvoke(context)) {
|
|
309
|
-
internalLogger.verbose("Receive Teams state verification request");
|
|
310
|
-
yield this.sendOAuthCardAsync(dc.context);
|
|
311
|
-
yield context.sendActivity({ type: invokeResponseType, value: { status: StatusCodes.OK } });
|
|
312
|
-
}
|
|
313
|
-
return tokenResponse !== undefined
|
|
314
|
-
? { succeeded: true, value: tokenResponse }
|
|
315
|
-
: { succeeded: false };
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* @internal
|
|
320
|
-
*/
|
|
321
|
-
getTokenExchangeInvokeResponse(status, failureDetail, id) {
|
|
322
|
-
const invokeResponse = {
|
|
323
|
-
type: invokeResponseType,
|
|
324
|
-
value: { status, body: new TokenExchangeInvokeResponse(id, failureDetail) },
|
|
325
|
-
};
|
|
326
|
-
return invokeResponse;
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* @internal
|
|
330
|
-
*/
|
|
331
|
-
isTeamsVerificationInvoke(context) {
|
|
332
|
-
const activity = context.activity;
|
|
333
|
-
return activity.type === ActivityTypes.Invoke && activity.name === verifyStateOperationName;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* @internal
|
|
337
|
-
*/
|
|
338
|
-
isTokenExchangeRequestInvoke(context) {
|
|
339
|
-
const activity = context.activity;
|
|
340
|
-
return activity.type === ActivityTypes.Invoke && activity.name === tokenExchangeOperationName;
|
|
341
|
-
}
|
|
342
|
-
/**
|
|
343
|
-
* @internal
|
|
344
|
-
*/
|
|
345
|
-
isTokenExchangeRequest(obj) {
|
|
346
|
-
return obj.hasOwnProperty("token");
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
//# sourceMappingURL=teamsBotSsoPrompt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"teamsBotSsoPrompt.js","sourceRoot":"","sources":["../../../src/bot/teamsBotSsoPrompt.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { AccessToken } from \"@azure/identity\";\nimport {\n Activity,\n ActivityTypes,\n CardFactory,\n Channels,\n MessageFactory,\n TurnContext,\n OAuthCard,\n ActionTypes,\n verifyStateOperationName,\n StatusCodes,\n TokenExchangeInvokeRequest,\n tokenExchangeOperationName,\n TokenExchangeResource,\n TeamsInfo,\n TeamsChannelAccount,\n} from \"botbuilder\";\nimport {\n Dialog,\n DialogContext,\n DialogTurnResult,\n PromptOptions,\n PromptRecognizerResult,\n} from \"botbuilder-dialogs\";\nimport { TeamsBotSsoPromptTokenResponse } from \"./teamsBotSsoPromptTokenResponse\";\nimport { config } from \"../core/configurationProvider\";\nimport { OnBehalfOfUserCredential } from \"../credential/onBehalfOfUserCredential\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { ErrorWithCode, ErrorCode, ErrorMessage } from \"../core/errors\";\nimport { internalLogger } from \"../util/logger\";\nimport { validateScopesType, formatString, parseJwt } from \"../util/utils\";\n\nconst invokeResponseType = \"invokeResponse\";\n/**\n * Response body returned for a token exchange invoke activity.\n *\n * @beta\n */\nclass TokenExchangeInvokeResponse {\n /**\n * Response id\n */\n id: string;\n\n /**\n * Detailed error message\n */\n failureDetail: string;\n\n constructor(id: string, failureDetail: string) {\n this.id = id;\n this.failureDetail = failureDetail;\n }\n}\n\n/**\n * Settings used to configure an TeamsBotSsoPrompt instance.\n *\n * @beta\n */\nexport interface TeamsBotSsoPromptSettings {\n /**\n * The array of strings that declare the desired permissions and the resources requested.\n */\n scopes: string[];\n\n /**\n * (Optional) number of milliseconds the prompt will wait for the user to authenticate.\n * Defaults to a value `900,000` (15 minutes.)\n */\n timeout?: number;\n\n /**\n * (Optional) value indicating whether the TeamsBotSsoPrompt should end upon receiving an\n * invalid message. Generally the TeamsBotSsoPrompt will end the auth flow when receives user\n * message not related to the auth flow. Setting the flag to false ignores the user's message instead.\n * Defaults to value `true`\n */\n endOnInvalidMessage?: boolean;\n}\n\n/**\n * Creates a new prompt that leverage Teams Single Sign On (SSO) support for bot to automatically sign in user and\n * help receive oauth token, asks the user to consent if needed.\n *\n * @remarks\n * The prompt will attempt to retrieve the users current token of the desired scopes and store it in\n * the token store.\n *\n * User will be automatically signed in leveraging Teams support of Bot Single Sign On(SSO):\n * https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/auth-aad-sso-bots\n *\n * @example\n * When used with your bots `DialogSet` you can simply add a new instance of the prompt as a named\n * dialog using `DialogSet.add()`. You can then start the prompt from a waterfall step using either\n * `DialogContext.beginDialog()` or `DialogContext.prompt()`. The user will be prompted to sign in as\n * needed and their access token will be passed as an argument to the callers next waterfall step:\n *\n * ```JavaScript\n * const { ConversationState, MemoryStorage } = require('botbuilder');\n * const { DialogSet, WaterfallDialog } = require('botbuilder-dialogs');\n * const { TeamsBotSsoPrompt } = require('@microsoft/teamsfx');\n *\n * const convoState = new ConversationState(new MemoryStorage());\n * const dialogState = convoState.createProperty('dialogState');\n * const dialogs = new DialogSet(dialogState);\n *\n * loadConfiguration();\n * dialogs.add(new TeamsBotSsoPrompt('TeamsBotSsoPrompt', {\n * scopes: [\"User.Read\"],\n * }));\n *\n * dialogs.add(new WaterfallDialog('taskNeedingLogin', [\n * async (step) => {\n * return await step.beginDialog('TeamsBotSsoPrompt');\n * },\n * async (step) => {\n * const token = step.result;\n * if (token) {\n *\n * // ... continue with task needing access token ...\n *\n * } else {\n * await step.context.sendActivity(`Sorry... We couldn't log you in. Try again later.`);\n * return await step.endDialog();\n * }\n * }\n * ]));\n * ```\n *\n * @beta\n */\nexport class TeamsBotSsoPrompt extends Dialog {\n /**\n * Constructor of TeamsBotSsoPrompt.\n *\n * @param dialogId Unique ID of the dialog within its parent `DialogSet` or `ComponentDialog`.\n * @param settings Settings used to configure the prompt.\n *\n * @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.\n * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.\n *\n * @beta\n */\n constructor(dialogId: string, private settings: TeamsBotSsoPromptSettings) {\n super(dialogId);\n validateScopesType(settings.scopes);\n internalLogger.info(\"Create a new Teams Bot SSO Prompt\");\n }\n\n /**\n * Called when a prompt dialog is pushed onto the dialog stack and is being activated.\n * @remarks\n * If the task is successful, the result indicates whether the prompt is still\n * active after the turn has been processed by the prompt.\n *\n * @param dc The DialogContext for the current turn of the conversation.\n *\n * @throws {@link ErrorCode|InvalidParameter} when timeout property in teams bot sso prompt settings is not number or is not positive.\n * @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.\n * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.\n *\n * @returns A `Promise` representing the asynchronous operation.\n *\n * @beta\n */\n public async beginDialog(dc: DialogContext): Promise<DialogTurnResult> {\n internalLogger.info(\"Begin Teams Bot SSO Prompt\");\n this.ensureMsTeamsChannel(dc);\n\n // Initialize prompt state\n const default_timeout = 900000;\n let timeout: number = default_timeout;\n if (this.settings.timeout) {\n if (typeof this.settings.timeout != \"number\") {\n const errorMsg = \"type of timeout property in teamsBotSsoPromptSettings should be number.\";\n internalLogger.error(errorMsg);\n throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);\n }\n if (this.settings.timeout <= 0) {\n const errorMsg =\n \"value of timeout property in teamsBotSsoPromptSettings should be positive.\";\n internalLogger.error(errorMsg);\n throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);\n }\n timeout = this.settings.timeout;\n }\n\n if (this.settings.endOnInvalidMessage === undefined) {\n this.settings.endOnInvalidMessage = true;\n }\n const state: teamsBotSsoPromptState = dc.activeDialog?.state as teamsBotSsoPromptState;\n state.state = {};\n state.options = {};\n state.expires = new Date().getTime() + timeout;\n\n // Send OAuth card to get SSO token\n await this.sendOAuthCardAsync(dc.context);\n return Dialog.EndOfTurn;\n }\n\n /**\n * Called when a prompt dialog is the active dialog and the user replied with a new activity.\n *\n * @remarks\n * If the task is successful, the result indicates whether the dialog is still\n * active after the turn has been processed by the dialog.\n * The prompt generally continues to receive the user's replies until it accepts the\n * user's reply as valid input for the prompt.\n *\n * @param dc The DialogContext for the current turn of the conversation.\n *\n * @returns A `Promise` representing the asynchronous operation.\n *\n * @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.\n * @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.\n *\n * @beta\n */\n public async continueDialog(dc: DialogContext): Promise<DialogTurnResult> {\n internalLogger.info(\"Continue Teams Bot SSO Prompt\");\n this.ensureMsTeamsChannel(dc);\n\n // Check for timeout\n const state: teamsBotSsoPromptState = dc.activeDialog?.state as teamsBotSsoPromptState;\n const isMessage: boolean = dc.context.activity.type === ActivityTypes.Message;\n const isTimeoutActivityType: boolean =\n isMessage ||\n this.isTeamsVerificationInvoke(dc.context) ||\n this.isTokenExchangeRequestInvoke(dc.context);\n\n // If the incoming Activity is a message, or an Activity Type normally handled by TeamsBotSsoPrompt,\n // check to see if this TeamsBotSsoPrompt Expiration has elapsed, and end the dialog if so.\n const hasTimedOut: boolean = isTimeoutActivityType && new Date().getTime() > state.expires;\n if (hasTimedOut) {\n internalLogger.warn(\"End Teams Bot SSO Prompt due to timeout\");\n return await dc.endDialog(undefined);\n } else {\n if (\n this.isTeamsVerificationInvoke(dc.context) ||\n this.isTokenExchangeRequestInvoke(dc.context)\n ) {\n // Recognize token\n const recognized: PromptRecognizerResult<TeamsBotSsoPromptTokenResponse> =\n await this.recognizeToken(dc);\n\n if (recognized.succeeded) {\n return await dc.endDialog(recognized.value);\n }\n } else if (isMessage && this.settings.endOnInvalidMessage) {\n internalLogger.warn(\"End Teams Bot SSO Prompt due to invalid message\");\n return await dc.endDialog(undefined);\n }\n\n return Dialog.EndOfTurn;\n }\n }\n\n /**\n * Ensure bot is running in MS Teams since TeamsBotSsoPrompt is only supported in MS Teams channel.\n * @param dc dialog context\n * @throws {@link ErrorCode|ChannelNotSupported} if bot channel is not MS Teams\n * @internal\n */\n private ensureMsTeamsChannel(dc: DialogContext) {\n if (dc.context.activity.channelId != Channels.Msteams) {\n const errorMsg = formatString(\n ErrorMessage.OnlyMSTeamsChannelSupported,\n \"Teams Bot SSO Prompt\"\n );\n internalLogger.error(errorMsg);\n throw new ErrorWithCode(errorMsg, ErrorCode.ChannelNotSupported);\n }\n }\n\n /**\n * Send OAuthCard that tells Teams to obtain an authentication token for the bot application.\n * For details see https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/auth-aad-sso-bots.\n *\n * @internal\n */\n private async sendOAuthCardAsync(context: TurnContext): Promise<void> {\n internalLogger.verbose(\"Send OAuth card to get SSO token\");\n\n const account: TeamsChannelAccount = await TeamsInfo.getMember(\n context,\n context.activity.from.id\n );\n internalLogger.verbose(\n \"Get Teams member account user principal name: \" + account.userPrincipalName\n );\n\n const loginHint: string = account.userPrincipalName ? account.userPrincipalName : \"\";\n const signInResource = this.getSignInResource(loginHint);\n const card = CardFactory.oauthCard(\n \"\",\n \"Teams SSO Sign In\",\n \"Sign In\",\n signInResource.signInLink,\n signInResource.tokenExchangeResource\n );\n (card.content as OAuthCard).buttons[0].type = ActionTypes.Signin;\n const msg: Partial<Activity> = MessageFactory.attachment(card);\n\n // Send prompt\n await context.sendActivity(msg);\n }\n\n /**\n * Get sign in resource.\n *\n * @throws {@link ErrorCode|InvalidConfiguration} if client id, tenant id or initiate login endpoint is not found in config.\n *\n * @internal\n */\n private getSignInResource(loginHint: string) {\n internalLogger.verbose(\"Get sign in authentication configuration\");\n const missingConfigurations: string[] = [];\n\n if (!config?.authentication?.initiateLoginEndpoint) {\n missingConfigurations.push(\"initiateLoginEndpoint\");\n }\n\n if (!config?.authentication?.clientId) {\n missingConfigurations.push(\"clientId\");\n }\n\n if (!config?.authentication?.tenantId) {\n missingConfigurations.push(\"tenantId\");\n }\n\n if (!config?.authentication?.applicationIdUri) {\n missingConfigurations.push(\"applicationIdUri\");\n }\n\n if (missingConfigurations.length != 0) {\n const errorMsg = formatString(\n ErrorMessage.InvalidConfiguration,\n missingConfigurations.join(\", \"),\n \"undefined\"\n );\n internalLogger.error(errorMsg);\n throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);\n }\n\n const signInLink = `${config.authentication!.initiateLoginEndpoint}?scope=${encodeURI(\n this.settings.scopes.join(\" \")\n )}&clientId=${config.authentication!.clientId}&tenantId=${\n config.authentication!.tenantId\n }&loginHint=${loginHint}`;\n\n internalLogger.verbose(\"Sign in link: \" + signInLink);\n\n const tokenExchangeResource: TokenExchangeResource = {\n id: uuidv4(),\n uri: config.authentication?.applicationIdUri!.replace(/\\/$/, \"\") + \"/access_as_user\",\n };\n\n internalLogger.verbose(\"Token exchange resource uri: \" + tokenExchangeResource.uri);\n\n return {\n signInLink: signInLink,\n tokenExchangeResource: tokenExchangeResource,\n };\n }\n\n /**\n * @internal\n */\n private async recognizeToken(\n dc: DialogContext\n ): Promise<PromptRecognizerResult<TeamsBotSsoPromptTokenResponse>> {\n const context = dc.context;\n let tokenResponse: TeamsBotSsoPromptTokenResponse | undefined;\n\n if (this.isTokenExchangeRequestInvoke(context)) {\n internalLogger.verbose(\"Receive token exchange request\");\n // Received activity is not a token exchange request\n if (!(context.activity.value && this.isTokenExchangeRequest(context.activity.value))) {\n const warningMsg =\n \"The bot received an InvokeActivity that is missing a TokenExchangeInvokeRequest value. This is required to be sent with the InvokeActivity.\";\n\n internalLogger.warn(warningMsg);\n await context.sendActivity(\n this.getTokenExchangeInvokeResponse(StatusCodes.BAD_REQUEST, warningMsg)\n );\n } else {\n const ssoToken = context.activity.value.token;\n const credential: OnBehalfOfUserCredential = new OnBehalfOfUserCredential(ssoToken);\n let exchangedToken: AccessToken | null;\n try {\n exchangedToken = await credential.getToken(this.settings.scopes);\n\n if (exchangedToken) {\n await context.sendActivity(\n this.getTokenExchangeInvokeResponse(StatusCodes.OK, \"\", context.activity.value.id)\n );\n\n const ssoTokenExpiration = parseJwt(ssoToken).exp;\n tokenResponse = {\n ssoToken: ssoToken,\n ssoTokenExpiration: new Date(ssoTokenExpiration * 1000).toISOString(),\n connectionName: \"\",\n token: exchangedToken.token,\n expiration: exchangedToken.expiresOnTimestamp.toString(),\n };\n }\n } catch (error) {\n const warningMsg = \"The bot is unable to exchange token. Ask for user consent.\";\n internalLogger.info(warningMsg);\n await context.sendActivity(\n this.getTokenExchangeInvokeResponse(\n StatusCodes.PRECONDITION_FAILED,\n warningMsg,\n context.activity.value.id\n )\n );\n }\n }\n } else if (this.isTeamsVerificationInvoke(context)) {\n internalLogger.verbose(\"Receive Teams state verification request\");\n await this.sendOAuthCardAsync(dc.context);\n await context.sendActivity({ type: invokeResponseType, value: { status: StatusCodes.OK } });\n }\n\n return tokenResponse !== undefined\n ? { succeeded: true, value: tokenResponse }\n : { succeeded: false };\n }\n\n /**\n * @internal\n */\n private getTokenExchangeInvokeResponse(\n status: number,\n failureDetail: string,\n id?: string\n ): Activity {\n const invokeResponse: Partial<Activity> = {\n type: invokeResponseType,\n value: { status, body: new TokenExchangeInvokeResponse(id as string, failureDetail) },\n };\n return invokeResponse as Activity;\n }\n\n /**\n * @internal\n */\n private isTeamsVerificationInvoke(context: TurnContext): boolean {\n const activity: Activity = context.activity;\n\n return activity.type === ActivityTypes.Invoke && activity.name === verifyStateOperationName;\n }\n\n /**\n * @internal\n */\n private isTokenExchangeRequestInvoke(context: TurnContext): boolean {\n const activity: Activity = context.activity;\n\n return activity.type === ActivityTypes.Invoke && activity.name === tokenExchangeOperationName;\n }\n\n /**\n * @internal\n */\n private isTokenExchangeRequest(obj: any): obj is TokenExchangeInvokeRequest {\n return obj.hasOwnProperty(\"token\");\n }\n}\n\n/**\n * @internal\n */\ninterface teamsBotSsoPromptState {\n state: any;\n options: PromptOptions;\n expires: number; // Timestamp of when the prompt will timeout.\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"teamsBotSsoPromptTokenResponse.js","sourceRoot":"","sources":["../../../src/bot/teamsBotSsoPromptTokenResponse.ts"],"names":[],"mappings":"","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\nimport { TokenResponse } from \"botframework-schema\";\n\n/**\n * Token response provided by Teams Bot SSO prompt\n *\n * @beta\n */\nexport interface TeamsBotSsoPromptTokenResponse extends TokenResponse {\n /**\n * SSO token for user\n */\n ssoToken: string;\n\n /**\n * Expire time of SSO token\n */\n ssoTokenExpiration: string;\n}\n"]}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT license.
|
|
3
|
-
/**
|
|
4
|
-
* Configuration used in initialization.
|
|
5
|
-
* @internal
|
|
6
|
-
*/
|
|
7
|
-
class Cache {
|
|
8
|
-
static get(key) {
|
|
9
|
-
return sessionStorage.getItem(key);
|
|
10
|
-
}
|
|
11
|
-
static set(key, value) {
|
|
12
|
-
sessionStorage.setItem(key, value);
|
|
13
|
-
}
|
|
14
|
-
static remove(key) {
|
|
15
|
-
sessionStorage.removeItem(key);
|
|
16
|
-
}
|
|
17
|
-
static clear() {
|
|
18
|
-
sessionStorage.clear();
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export { Cache };
|
|
22
|
-
//# sourceMappingURL=cache.browser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.browser.js","sourceRoot":"","sources":["../../../src/core/cache.browser.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC;;;GAGG;AACH,MAAM,KAAK;IACF,MAAM,CAAC,GAAG,CAAC,GAAW;QAC3B,OAAO,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;IAEM,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAC1C,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAEM,MAAM,CAAC,MAAM,CAAC,GAAW;QAC9B,cAAc,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;IACjC,CAAC;IAEM,MAAM,CAAC,KAAK;QACjB,cAAc,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;CACF;AAED,OAAO,EAAE,KAAK,EAAE,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\n/**\n * Configuration used in initialization.\n * @internal\n */\nclass Cache {\n public static get(key: string): string | null {\n return sessionStorage.getItem(key);\n }\n\n public static set(key: string, value: string): void {\n sessionStorage.setItem(key, value);\n }\n\n public static remove(key: string): void {\n sessionStorage.removeItem(key);\n }\n\n public static clear(): void {\n sessionStorage.clear();\n }\n}\n\nexport { Cache };\n"]}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Microsoft Corporation.
|
|
2
|
-
// Licensed under the MIT license.
|
|
3
|
-
import { CacheClass } from "memory-cache";
|
|
4
|
-
const cache = new CacheClass();
|
|
5
|
-
/**
|
|
6
|
-
* Cache based on memory.
|
|
7
|
-
*
|
|
8
|
-
* @remarks
|
|
9
|
-
* It will be used in server SDK.
|
|
10
|
-
*
|
|
11
|
-
* @internal
|
|
12
|
-
*/
|
|
13
|
-
class Cache {
|
|
14
|
-
static get(key) {
|
|
15
|
-
return cache.get(key);
|
|
16
|
-
}
|
|
17
|
-
static set(key, value) {
|
|
18
|
-
cache.put(key, value);
|
|
19
|
-
}
|
|
20
|
-
static remove(key) {
|
|
21
|
-
cache.del(key);
|
|
22
|
-
}
|
|
23
|
-
static clear() {
|
|
24
|
-
cache.clear();
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export { Cache };
|
|
28
|
-
//# sourceMappingURL=cache.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/core/cache.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAElC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,KAAK,GAAG,IAAI,UAAU,EAAkB,CAAC;AAE/C;;;;;;;GAOG;AACH,MAAM,KAAK;IACF,MAAM,CAAC,GAAG,CAAC,GAAW;QAC3B,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAEM,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAC1C,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxB,CAAC;IAEM,MAAM,CAAC,MAAM,CAAC,GAAW;QAC9B,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACjB,CAAC;IAEM,MAAM,CAAC,KAAK;QACjB,KAAK,CAAC,KAAK,EAAE,CAAC;IAChB,CAAC;CACF;AAED,OAAO,EAAE,KAAK,EAAE,CAAC","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT license.\n\nimport { CacheClass } from \"memory-cache\";\n\nconst cache = new CacheClass<string, string>();\n\n/**\n * Cache based on memory.\n *\n * @remarks\n * It will be used in server SDK.\n *\n * @internal\n */\nclass Cache {\n public static get(key: string): string | null {\n return cache.get(key);\n }\n\n public static set(key: string, value: string): void {\n cache.put(key, value);\n }\n\n public static remove(key: string): void {\n cache.del(key);\n }\n\n public static clear(): void {\n cache.clear();\n }\n}\n\nexport { Cache };\n"]}
|