@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
|
@@ -0,0 +1,1575 @@
|
|
|
1
|
+
import { __extends, __awaiter, __generator } from 'tslib';
|
|
2
|
+
import jwt_decode from 'jwt-decode';
|
|
3
|
+
import * as microsoftTeams from '@microsoft/teams-js';
|
|
4
|
+
import axios from 'axios';
|
|
5
|
+
import { Client } from '@microsoft/microsoft-graph-client';
|
|
6
|
+
import { ManagedIdentityCredential } from '@azure/identity';
|
|
7
|
+
|
|
8
|
+
// Copyright (c) Microsoft Corporation.
|
|
9
|
+
/**
|
|
10
|
+
* Error code to trace the error types.
|
|
11
|
+
* @beta
|
|
12
|
+
*/
|
|
13
|
+
var ErrorCode;
|
|
14
|
+
(function (ErrorCode) {
|
|
15
|
+
/**
|
|
16
|
+
* Invalid parameter error.
|
|
17
|
+
*/
|
|
18
|
+
ErrorCode["InvalidParameter"] = "InvalidParameter";
|
|
19
|
+
/**
|
|
20
|
+
* Invalid configuration error.
|
|
21
|
+
*/
|
|
22
|
+
ErrorCode["InvalidConfiguration"] = "InvalidConfiguration";
|
|
23
|
+
/**
|
|
24
|
+
* Invalid certificate error.
|
|
25
|
+
*/
|
|
26
|
+
ErrorCode["InvalidCertificate"] = "InvalidCertificate";
|
|
27
|
+
/**
|
|
28
|
+
* Internal error.
|
|
29
|
+
*/
|
|
30
|
+
ErrorCode["InternalError"] = "InternalError";
|
|
31
|
+
/**
|
|
32
|
+
* Channel is not supported error.
|
|
33
|
+
*/
|
|
34
|
+
ErrorCode["ChannelNotSupported"] = "ChannelNotSupported";
|
|
35
|
+
/**
|
|
36
|
+
* Runtime is not supported error.
|
|
37
|
+
*/
|
|
38
|
+
ErrorCode["RuntimeNotSupported"] = "RuntimeNotSupported";
|
|
39
|
+
/**
|
|
40
|
+
* User failed to finish the AAD consent flow failed.
|
|
41
|
+
*/
|
|
42
|
+
ErrorCode["ConsentFailed"] = "ConsentFailed";
|
|
43
|
+
/**
|
|
44
|
+
* The user or administrator has not consented to use the application error.
|
|
45
|
+
*/
|
|
46
|
+
ErrorCode["UiRequiredError"] = "UiRequiredError";
|
|
47
|
+
/**
|
|
48
|
+
* Token is not within its valid time range error.
|
|
49
|
+
*/
|
|
50
|
+
ErrorCode["TokenExpiredError"] = "TokenExpiredError";
|
|
51
|
+
/**
|
|
52
|
+
* Call service (AAD or simple authentication server) failed.
|
|
53
|
+
*/
|
|
54
|
+
ErrorCode["ServiceError"] = "ServiceError";
|
|
55
|
+
/**
|
|
56
|
+
* Operation failed.
|
|
57
|
+
*/
|
|
58
|
+
ErrorCode["FailedOperation"] = "FailedOperation";
|
|
59
|
+
})(ErrorCode || (ErrorCode = {}));
|
|
60
|
+
/**
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
var ErrorMessage = /** @class */ (function () {
|
|
64
|
+
function ErrorMessage() {
|
|
65
|
+
}
|
|
66
|
+
// InvalidConfiguration Error
|
|
67
|
+
ErrorMessage.InvalidConfiguration = "{0} in configuration is invalid: {1}.";
|
|
68
|
+
ErrorMessage.ConfigurationNotExists = "Configuration does not exist. {0}";
|
|
69
|
+
ErrorMessage.ResourceConfigurationNotExists = "{0} resource configuration does not exist.";
|
|
70
|
+
ErrorMessage.MissingResourceConfiguration = "Missing resource configuration with type: {0}, name: {1}.";
|
|
71
|
+
ErrorMessage.AuthenticationConfigurationNotExists = "Authentication configuration does not exist.";
|
|
72
|
+
// RuntimeNotSupported Error
|
|
73
|
+
ErrorMessage.BrowserRuntimeNotSupported = "{0} is not supported in browser.";
|
|
74
|
+
ErrorMessage.NodejsRuntimeNotSupported = "{0} is not supported in Node.";
|
|
75
|
+
// Internal Error
|
|
76
|
+
ErrorMessage.FailToAcquireTokenOnBehalfOfUser = "Failed to acquire access token on behalf of user: {0}";
|
|
77
|
+
// ChannelNotSupported Error
|
|
78
|
+
ErrorMessage.OnlyMSTeamsChannelSupported = "{0} is only supported in MS Teams Channel";
|
|
79
|
+
return ErrorMessage;
|
|
80
|
+
}());
|
|
81
|
+
/**
|
|
82
|
+
* Error class with code and message thrown by the SDK.
|
|
83
|
+
*
|
|
84
|
+
* @beta
|
|
85
|
+
*/
|
|
86
|
+
var ErrorWithCode = /** @class */ (function (_super) {
|
|
87
|
+
__extends(ErrorWithCode, _super);
|
|
88
|
+
/**
|
|
89
|
+
* Constructor of ErrorWithCode.
|
|
90
|
+
*
|
|
91
|
+
* @param {string} message - error message.
|
|
92
|
+
* @param {ErrorCode} code - error code.
|
|
93
|
+
*
|
|
94
|
+
* @beta
|
|
95
|
+
*/
|
|
96
|
+
function ErrorWithCode(message, code) {
|
|
97
|
+
var _newTarget = this.constructor;
|
|
98
|
+
var _this = this;
|
|
99
|
+
if (!code) {
|
|
100
|
+
_this = _super.call(this, message) || this;
|
|
101
|
+
return _this;
|
|
102
|
+
}
|
|
103
|
+
_this = _super.call(this, message) || this;
|
|
104
|
+
Object.setPrototypeOf(_this, ErrorWithCode.prototype);
|
|
105
|
+
_this.name = _newTarget.name + "." + code;
|
|
106
|
+
_this.code = code;
|
|
107
|
+
return _this;
|
|
108
|
+
}
|
|
109
|
+
return ErrorWithCode;
|
|
110
|
+
}(Error));
|
|
111
|
+
|
|
112
|
+
// Copyright (c) Microsoft Corporation.
|
|
113
|
+
// Licensed under the MIT license.
|
|
114
|
+
/**
|
|
115
|
+
* Available resource type.
|
|
116
|
+
* @beta
|
|
117
|
+
*/
|
|
118
|
+
var ResourceType;
|
|
119
|
+
(function (ResourceType) {
|
|
120
|
+
/**
|
|
121
|
+
* SQL database.
|
|
122
|
+
*
|
|
123
|
+
*/
|
|
124
|
+
ResourceType[ResourceType["SQL"] = 0] = "SQL";
|
|
125
|
+
/**
|
|
126
|
+
* Rest API.
|
|
127
|
+
*
|
|
128
|
+
*/
|
|
129
|
+
ResourceType[ResourceType["API"] = 1] = "API";
|
|
130
|
+
})(ResourceType || (ResourceType = {}));
|
|
131
|
+
|
|
132
|
+
// Copyright (c) Microsoft Corporation.
|
|
133
|
+
// Licensed under the MIT license.
|
|
134
|
+
/**
|
|
135
|
+
* Log level.
|
|
136
|
+
*
|
|
137
|
+
* @beta
|
|
138
|
+
*/
|
|
139
|
+
var LogLevel;
|
|
140
|
+
(function (LogLevel) {
|
|
141
|
+
/**
|
|
142
|
+
* Show verbose, information, warning and error message.
|
|
143
|
+
*/
|
|
144
|
+
LogLevel[LogLevel["Verbose"] = 0] = "Verbose";
|
|
145
|
+
/**
|
|
146
|
+
* Show information, warning and error message.
|
|
147
|
+
*/
|
|
148
|
+
LogLevel[LogLevel["Info"] = 1] = "Info";
|
|
149
|
+
/**
|
|
150
|
+
* Show warning and error message.
|
|
151
|
+
*/
|
|
152
|
+
LogLevel[LogLevel["Warn"] = 2] = "Warn";
|
|
153
|
+
/**
|
|
154
|
+
* Show error message.
|
|
155
|
+
*/
|
|
156
|
+
LogLevel[LogLevel["Error"] = 3] = "Error";
|
|
157
|
+
})(LogLevel || (LogLevel = {}));
|
|
158
|
+
/**
|
|
159
|
+
* Update log level helper.
|
|
160
|
+
*
|
|
161
|
+
* @param { LogLevel } level - log level in configuration
|
|
162
|
+
*
|
|
163
|
+
* @beta
|
|
164
|
+
*/
|
|
165
|
+
function setLogLevel(level) {
|
|
166
|
+
internalLogger.level = level;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Get log level.
|
|
170
|
+
*
|
|
171
|
+
* @returns Log level
|
|
172
|
+
*
|
|
173
|
+
* @beta
|
|
174
|
+
*/
|
|
175
|
+
function getLogLevel() {
|
|
176
|
+
return internalLogger.level;
|
|
177
|
+
}
|
|
178
|
+
var InternalLogger = /** @class */ (function () {
|
|
179
|
+
function InternalLogger() {
|
|
180
|
+
this.level = undefined;
|
|
181
|
+
this.defaultLogger = {
|
|
182
|
+
verbose: console.debug,
|
|
183
|
+
info: console.info,
|
|
184
|
+
warn: console.warn,
|
|
185
|
+
error: console.error,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
InternalLogger.prototype.error = function (message) {
|
|
189
|
+
this.log(LogLevel.Error, function (x) { return x.error; }, message);
|
|
190
|
+
};
|
|
191
|
+
InternalLogger.prototype.warn = function (message) {
|
|
192
|
+
this.log(LogLevel.Warn, function (x) { return x.warn; }, message);
|
|
193
|
+
};
|
|
194
|
+
InternalLogger.prototype.info = function (message) {
|
|
195
|
+
this.log(LogLevel.Info, function (x) { return x.info; }, message);
|
|
196
|
+
};
|
|
197
|
+
InternalLogger.prototype.verbose = function (message) {
|
|
198
|
+
this.log(LogLevel.Verbose, function (x) { return x.verbose; }, message);
|
|
199
|
+
};
|
|
200
|
+
InternalLogger.prototype.log = function (logLevel, logFunction, message) {
|
|
201
|
+
if (message.trim() === "") {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
var timestamp = new Date().toUTCString();
|
|
205
|
+
var logHeader = "[" + timestamp + "] : @microsoft/teamsfx : " + LogLevel[logLevel] + " - ";
|
|
206
|
+
var logMessage = "" + logHeader + message;
|
|
207
|
+
if (this.level !== undefined && this.level <= logLevel) {
|
|
208
|
+
if (this.customLogger) {
|
|
209
|
+
logFunction(this.customLogger)(logMessage);
|
|
210
|
+
}
|
|
211
|
+
else if (this.customLogFunction) {
|
|
212
|
+
this.customLogFunction(logLevel, logMessage);
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
logFunction(this.defaultLogger)(logMessage);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
return InternalLogger;
|
|
220
|
+
}());
|
|
221
|
+
/**
|
|
222
|
+
* Logger instance used internally
|
|
223
|
+
*
|
|
224
|
+
* @internal
|
|
225
|
+
*/
|
|
226
|
+
var internalLogger = new InternalLogger();
|
|
227
|
+
/**
|
|
228
|
+
* Set custom logger. Use the output functions if it's set. Priority is higher than setLogFunction.
|
|
229
|
+
*
|
|
230
|
+
* @param {Logger} logger - custom logger. If it's undefined, custom logger will be cleared.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* setLogger({
|
|
235
|
+
* verbose: console.debug,
|
|
236
|
+
* info: console.info,
|
|
237
|
+
* warn: console.warn,
|
|
238
|
+
* error: console.error,
|
|
239
|
+
* });
|
|
240
|
+
* ```
|
|
241
|
+
*
|
|
242
|
+
* @beta
|
|
243
|
+
*/
|
|
244
|
+
function setLogger(logger) {
|
|
245
|
+
internalLogger.customLogger = logger;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Set custom log function. Use the function if it's set. Priority is lower than setLogger.
|
|
249
|
+
*
|
|
250
|
+
* @param {LogFunction} logFunction - custom log function. If it's undefined, custom log function will be cleared.
|
|
251
|
+
*
|
|
252
|
+
* @example
|
|
253
|
+
* ```typescript
|
|
254
|
+
* setLogFunction((level: LogLevel, message: string) => {
|
|
255
|
+
* if (level === LogLevel.Error) {
|
|
256
|
+
* console.log(message);
|
|
257
|
+
* }
|
|
258
|
+
* });
|
|
259
|
+
* ```
|
|
260
|
+
*
|
|
261
|
+
* @beta
|
|
262
|
+
*/
|
|
263
|
+
function setLogFunction(logFunction) {
|
|
264
|
+
internalLogger.customLogFunction = logFunction;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Copyright (c) Microsoft Corporation.
|
|
268
|
+
/**
|
|
269
|
+
* Parse jwt token payload
|
|
270
|
+
*
|
|
271
|
+
* @param token
|
|
272
|
+
*
|
|
273
|
+
* @returns Payload object
|
|
274
|
+
*
|
|
275
|
+
* @internal
|
|
276
|
+
*/
|
|
277
|
+
function parseJwt(token) {
|
|
278
|
+
try {
|
|
279
|
+
var tokenObj = jwt_decode(token);
|
|
280
|
+
if (!tokenObj || !tokenObj.exp) {
|
|
281
|
+
throw new ErrorWithCode("Decoded token is null or exp claim does not exists.", ErrorCode.InternalError);
|
|
282
|
+
}
|
|
283
|
+
return tokenObj;
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
var errorMsg = "Parse jwt token failed in node env with error: " + err.message;
|
|
287
|
+
internalLogger.error(errorMsg);
|
|
288
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InternalError);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* @internal
|
|
293
|
+
*/
|
|
294
|
+
function getUserInfoFromSsoToken(ssoToken) {
|
|
295
|
+
if (!ssoToken) {
|
|
296
|
+
var errorMsg = "SSO token is undefined.";
|
|
297
|
+
internalLogger.error(errorMsg);
|
|
298
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);
|
|
299
|
+
}
|
|
300
|
+
var tokenObject = parseJwt(ssoToken);
|
|
301
|
+
var userInfo = {
|
|
302
|
+
displayName: tokenObject.name,
|
|
303
|
+
objectId: tokenObject.oid,
|
|
304
|
+
preferredUserName: "",
|
|
305
|
+
};
|
|
306
|
+
if (tokenObject.ver === "2.0") {
|
|
307
|
+
userInfo.preferredUserName = tokenObject.preferred_username;
|
|
308
|
+
}
|
|
309
|
+
else if (tokenObject.ver === "1.0") {
|
|
310
|
+
userInfo.preferredUserName = tokenObject.upn;
|
|
311
|
+
}
|
|
312
|
+
return userInfo;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Format string template with replacements
|
|
316
|
+
*
|
|
317
|
+
* ```typescript
|
|
318
|
+
* const template = "{0} and {1} are fruit. {0} is my favorite one."
|
|
319
|
+
* const formattedStr = formatString(template, "apple", "pear"); // formattedStr: "apple and pear are fruit. apple is my favorite one."
|
|
320
|
+
* ```
|
|
321
|
+
*
|
|
322
|
+
* @param str string template
|
|
323
|
+
* @param replacements replacement string array
|
|
324
|
+
* @returns Formatted string
|
|
325
|
+
*
|
|
326
|
+
* @internal
|
|
327
|
+
*/
|
|
328
|
+
function formatString(str) {
|
|
329
|
+
var replacements = [];
|
|
330
|
+
for (var _i = 1; _i < arguments.length; _i++) {
|
|
331
|
+
replacements[_i - 1] = arguments[_i];
|
|
332
|
+
}
|
|
333
|
+
var args = replacements;
|
|
334
|
+
return str.replace(/{(\d+)}/g, function (match, number) {
|
|
335
|
+
return typeof args[number] != "undefined" ? args[number] : match;
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* @internal
|
|
340
|
+
*/
|
|
341
|
+
function validateScopesType(value) {
|
|
342
|
+
// string
|
|
343
|
+
if (typeof value === "string" || value instanceof String) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
// empty array
|
|
347
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
// string array
|
|
351
|
+
if (Array.isArray(value) && value.length > 0 && value.every(function (item) { return typeof item === "string"; })) {
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
var errorMsg = "The type of scopes is not valid, it must be string or string array";
|
|
355
|
+
internalLogger.error(errorMsg);
|
|
356
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* @internal
|
|
360
|
+
*/
|
|
361
|
+
var isNode = typeof process !== "undefined" &&
|
|
362
|
+
!!process.version &&
|
|
363
|
+
!!process.versions &&
|
|
364
|
+
!!process.versions.node;
|
|
365
|
+
|
|
366
|
+
// Copyright (c) Microsoft Corporation.
|
|
367
|
+
/**
|
|
368
|
+
* Global configuration instance
|
|
369
|
+
*
|
|
370
|
+
*/
|
|
371
|
+
var config;
|
|
372
|
+
/**
|
|
373
|
+
* Initialize configuration from environment variables or configuration object and set the global instance
|
|
374
|
+
*
|
|
375
|
+
* @param {Configuration} configuration - Optional configuration that overrides the default configuration values. The override depth is 1.
|
|
376
|
+
*
|
|
377
|
+
* @throws {@link ErrorCode|InvalidParameter} when configuration is not passed in browser environment
|
|
378
|
+
*
|
|
379
|
+
* @beta
|
|
380
|
+
*/
|
|
381
|
+
function loadConfiguration(configuration) {
|
|
382
|
+
internalLogger.info("load configuration");
|
|
383
|
+
// browser environment
|
|
384
|
+
if (!isNode) {
|
|
385
|
+
if (!configuration) {
|
|
386
|
+
var errorMsg = "You are running the code in browser. Configuration must be passed in.";
|
|
387
|
+
internalLogger.error(errorMsg);
|
|
388
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);
|
|
389
|
+
}
|
|
390
|
+
config = configuration;
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
// node environment
|
|
394
|
+
var newAuthentication;
|
|
395
|
+
var newResources = [];
|
|
396
|
+
var defaultResourceName = "default";
|
|
397
|
+
if (configuration === null || configuration === void 0 ? void 0 : configuration.authentication) {
|
|
398
|
+
newAuthentication = configuration.authentication;
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
newAuthentication = {
|
|
402
|
+
authorityHost: process.env.M365_AUTHORITY_HOST,
|
|
403
|
+
tenantId: process.env.M365_TENANT_ID,
|
|
404
|
+
clientId: process.env.M365_CLIENT_ID,
|
|
405
|
+
clientSecret: process.env.M365_CLIENT_SECRET,
|
|
406
|
+
simpleAuthEndpoint: process.env.SIMPLE_AUTH_ENDPOINT,
|
|
407
|
+
initiateLoginEndpoint: process.env.INITIATE_LOGIN_ENDPOINT,
|
|
408
|
+
applicationIdUri: process.env.M365_APPLICATION_ID_URI,
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
if (configuration === null || configuration === void 0 ? void 0 : configuration.resources) {
|
|
412
|
+
newResources = configuration.resources;
|
|
413
|
+
}
|
|
414
|
+
else {
|
|
415
|
+
newResources = [
|
|
416
|
+
{
|
|
417
|
+
// SQL resource
|
|
418
|
+
type: ResourceType.SQL,
|
|
419
|
+
name: defaultResourceName,
|
|
420
|
+
properties: {
|
|
421
|
+
sqlServerEndpoint: process.env.SQL_ENDPOINT,
|
|
422
|
+
sqlUsername: process.env.SQL_USER_NAME,
|
|
423
|
+
sqlPassword: process.env.SQL_PASSWORD,
|
|
424
|
+
sqlDatabaseName: process.env.SQL_DATABASE_NAME,
|
|
425
|
+
sqlIdentityId: process.env.IDENTITY_ID,
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
// API resource
|
|
430
|
+
type: ResourceType.API,
|
|
431
|
+
name: defaultResourceName,
|
|
432
|
+
properties: {
|
|
433
|
+
endpoint: process.env.API_ENDPOINT,
|
|
434
|
+
},
|
|
435
|
+
},
|
|
436
|
+
];
|
|
437
|
+
}
|
|
438
|
+
config = {
|
|
439
|
+
authentication: newAuthentication,
|
|
440
|
+
resources: newResources,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Get configuration for a specific resource.
|
|
445
|
+
* @param {ResourceType} resourceType - The type of resource
|
|
446
|
+
* @param {string} resourceName - The name of resource, default value is "default".
|
|
447
|
+
*
|
|
448
|
+
* @returns Resource configuration for target resource from global configuration instance.
|
|
449
|
+
*
|
|
450
|
+
* @throws {@link ErrorCode|InvalidConfiguration} when resource configuration with the specific type and name is not found
|
|
451
|
+
*
|
|
452
|
+
* @beta
|
|
453
|
+
*/
|
|
454
|
+
function getResourceConfiguration(resourceType, resourceName) {
|
|
455
|
+
var _a;
|
|
456
|
+
if (resourceName === void 0) { resourceName = "default"; }
|
|
457
|
+
internalLogger.info("Get resource configuration of " + ResourceType[resourceType] + " from " + resourceName);
|
|
458
|
+
var result = (_a = config.resources) === null || _a === void 0 ? void 0 : _a.find(function (item) { return item.type === resourceType && item.name === resourceName; });
|
|
459
|
+
if (result) {
|
|
460
|
+
return result.properties;
|
|
461
|
+
}
|
|
462
|
+
var errorMsg = formatString(ErrorMessage.MissingResourceConfiguration, ResourceType[resourceType], resourceName);
|
|
463
|
+
internalLogger.error(errorMsg);
|
|
464
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Get configuration for authentication.
|
|
468
|
+
*
|
|
469
|
+
* @returns Authentication configuration from global configuration instance, the value may be undefined if no authentication config exists in current environment.
|
|
470
|
+
*
|
|
471
|
+
* @throws {@link ErrorCode|InvalidConfiguration} when global configuration does not exist
|
|
472
|
+
*
|
|
473
|
+
* @beta
|
|
474
|
+
*/
|
|
475
|
+
function getAuthenticationConfiguration() {
|
|
476
|
+
internalLogger.info("Get authentication configuration");
|
|
477
|
+
if (config) {
|
|
478
|
+
return config.authentication;
|
|
479
|
+
}
|
|
480
|
+
var errorMsg = "Please call loadConfiguration() first before calling getAuthenticationConfiguration().";
|
|
481
|
+
internalLogger.error(errorMsg);
|
|
482
|
+
throw new ErrorWithCode(formatString(ErrorMessage.ConfigurationNotExists, errorMsg), ErrorCode.InvalidConfiguration);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
// Copyright (c) Microsoft Corporation.
|
|
486
|
+
/**
|
|
487
|
+
* Represent Microsoft 365 tenant identity, and it is usually used when user is not involved.
|
|
488
|
+
*
|
|
489
|
+
* @remarks
|
|
490
|
+
* Only works in in server side.
|
|
491
|
+
*
|
|
492
|
+
* @beta
|
|
493
|
+
*/
|
|
494
|
+
var M365TenantCredential = /** @class */ (function () {
|
|
495
|
+
/**
|
|
496
|
+
* Constructor of M365TenantCredential.
|
|
497
|
+
*
|
|
498
|
+
* @remarks
|
|
499
|
+
* Only works in in server side.
|
|
500
|
+
* @beta
|
|
501
|
+
*/
|
|
502
|
+
function M365TenantCredential() {
|
|
503
|
+
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "M365TenantCredential"), ErrorCode.RuntimeNotSupported);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Get access token for credential.
|
|
507
|
+
*
|
|
508
|
+
* @remarks
|
|
509
|
+
* Only works in in server side.
|
|
510
|
+
* @beta
|
|
511
|
+
*/
|
|
512
|
+
M365TenantCredential.prototype.getToken = function (scopes, options) {
|
|
513
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
514
|
+
return __generator(this, function (_a) {
|
|
515
|
+
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "M365TenantCredential"), ErrorCode.RuntimeNotSupported);
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
};
|
|
519
|
+
return M365TenantCredential;
|
|
520
|
+
}());
|
|
521
|
+
|
|
522
|
+
// Copyright (c) Microsoft Corporation.
|
|
523
|
+
/**
|
|
524
|
+
* Represent on-behalf-of flow to get user identity, and it is designed to be used in Azure Function or Bot scenarios.
|
|
525
|
+
*
|
|
526
|
+
* @remarks
|
|
527
|
+
* Can only be used in server side.
|
|
528
|
+
*
|
|
529
|
+
* @beta
|
|
530
|
+
*/
|
|
531
|
+
var OnBehalfOfUserCredential = /** @class */ (function () {
|
|
532
|
+
/**
|
|
533
|
+
* Constructor of OnBehalfOfUserCredential
|
|
534
|
+
*
|
|
535
|
+
* @remarks
|
|
536
|
+
* Can Only works in in server side.
|
|
537
|
+
* @beta
|
|
538
|
+
*/
|
|
539
|
+
function OnBehalfOfUserCredential(ssoToken) {
|
|
540
|
+
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "OnBehalfOfUserCredential"), ErrorCode.RuntimeNotSupported);
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Get access token from credential.
|
|
544
|
+
* @remarks
|
|
545
|
+
* Can only be used in server side.
|
|
546
|
+
* @beta
|
|
547
|
+
*/
|
|
548
|
+
OnBehalfOfUserCredential.prototype.getToken = function (scopes, options) {
|
|
549
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
550
|
+
return __generator(this, function (_a) {
|
|
551
|
+
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "OnBehalfOfUserCredential"), ErrorCode.RuntimeNotSupported);
|
|
552
|
+
});
|
|
553
|
+
});
|
|
554
|
+
};
|
|
555
|
+
/**
|
|
556
|
+
* Get basic user info from SSO token.
|
|
557
|
+
* @remarks
|
|
558
|
+
* Can only be used in server side.
|
|
559
|
+
* @beta
|
|
560
|
+
*/
|
|
561
|
+
OnBehalfOfUserCredential.prototype.getUserInfo = function () {
|
|
562
|
+
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "OnBehalfOfUserCredential"), ErrorCode.RuntimeNotSupported);
|
|
563
|
+
};
|
|
564
|
+
return OnBehalfOfUserCredential;
|
|
565
|
+
}());
|
|
566
|
+
|
|
567
|
+
// Copyright (c) Microsoft Corporation.
|
|
568
|
+
// Licensed under the MIT license.
|
|
569
|
+
/**
|
|
570
|
+
* Configuration used in initialization.
|
|
571
|
+
* @internal
|
|
572
|
+
*/
|
|
573
|
+
var Cache = /** @class */ (function () {
|
|
574
|
+
function Cache() {
|
|
575
|
+
}
|
|
576
|
+
Cache.get = function (key) {
|
|
577
|
+
return sessionStorage.getItem(key);
|
|
578
|
+
};
|
|
579
|
+
Cache.set = function (key, value) {
|
|
580
|
+
sessionStorage.setItem(key, value);
|
|
581
|
+
};
|
|
582
|
+
Cache.remove = function (key) {
|
|
583
|
+
sessionStorage.removeItem(key);
|
|
584
|
+
};
|
|
585
|
+
return Cache;
|
|
586
|
+
}());
|
|
587
|
+
|
|
588
|
+
// Copyright (c) Microsoft Corporation.
|
|
589
|
+
// Licensed under the MIT license.
|
|
590
|
+
/**
|
|
591
|
+
* @internal
|
|
592
|
+
*/
|
|
593
|
+
var GrantType;
|
|
594
|
+
(function (GrantType) {
|
|
595
|
+
GrantType["authCode"] = "authorization_code";
|
|
596
|
+
GrantType["ssoToken"] = "sso_token";
|
|
597
|
+
})(GrantType || (GrantType = {}));
|
|
598
|
+
|
|
599
|
+
// Copyright (c) Microsoft Corporation.
|
|
600
|
+
var accessTokenCacheKeyPrefix = "accessToken";
|
|
601
|
+
var separator = "-";
|
|
602
|
+
var tokenRefreshTimeSpanInMillisecond = 5 * 60 * 1000;
|
|
603
|
+
var initializeTeamsSdkTimeoutInMillisecond = 5000;
|
|
604
|
+
var loginPageWidth = 600;
|
|
605
|
+
var loginPageHeight = 535;
|
|
606
|
+
var maxRetryCount = 3;
|
|
607
|
+
var retryTimeSpanInMillisecond = 3000;
|
|
608
|
+
/**
|
|
609
|
+
* Represent Teams current user's identity, and it is used within Teams tab application.
|
|
610
|
+
*
|
|
611
|
+
* @remarks
|
|
612
|
+
* Can only be used within Teams.
|
|
613
|
+
*
|
|
614
|
+
* @beta
|
|
615
|
+
*/
|
|
616
|
+
var TeamsUserCredential = /** @class */ (function () {
|
|
617
|
+
/**
|
|
618
|
+
* Constructor of TeamsUserCredential.
|
|
619
|
+
* Developer need to call loadConfiguration(config) before using this class.
|
|
620
|
+
*
|
|
621
|
+
* @example
|
|
622
|
+
* ```typescript
|
|
623
|
+
* const config = {
|
|
624
|
+
* authentication: {
|
|
625
|
+
* runtimeConnectorEndpoint: "https://xxx.xxx.com",
|
|
626
|
+
* initiateLoginEndpoint: "https://localhost:3000/auth-start.html",
|
|
627
|
+
* clientId: "xxx"
|
|
628
|
+
* }
|
|
629
|
+
* }
|
|
630
|
+
loadConfiguration(config); // No default config from environment variables, developers must provide the config object.
|
|
631
|
+
const credential = new TeamsUserCredential(["https://graph.microsoft.com/User.Read"]);
|
|
632
|
+
* ```
|
|
633
|
+
*
|
|
634
|
+
* @throws {@link ErrorCode|InvalidConfiguration} when client id, initiate login endpoint or simple auth endpoint is not found in config.
|
|
635
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
636
|
+
*
|
|
637
|
+
* @beta
|
|
638
|
+
*/
|
|
639
|
+
function TeamsUserCredential() {
|
|
640
|
+
internalLogger.info("Create teams user credential");
|
|
641
|
+
this.config = this.loadAndValidateConfig();
|
|
642
|
+
this.ssoToken = null;
|
|
643
|
+
}
|
|
644
|
+
/**
|
|
645
|
+
* Popup login page to get user's access token with specific scopes.
|
|
646
|
+
*
|
|
647
|
+
* @remarks
|
|
648
|
+
* Only works in Teams client APP. User will be redirected to the authorization page to login and consent.
|
|
649
|
+
*
|
|
650
|
+
* @example
|
|
651
|
+
* ```typescript
|
|
652
|
+
* await credential.login(["https://graph.microsoft.com/User.Read"]); // single scope using string array
|
|
653
|
+
* await credential.login("https://graph.microsoft.com/User.Read"); // single scopes using string
|
|
654
|
+
* await credential.login(["https://graph.microsoft.com/User.Read", "Calendars.Read"]); // multiple scopes using string array
|
|
655
|
+
* await credential.login("https://graph.microsoft.com/User.Read Calendars.Read"); // multiple scopes using string
|
|
656
|
+
* ```
|
|
657
|
+
* @param scopes - The list of scopes for which the token will have access, before that, we will request user to consent.
|
|
658
|
+
*
|
|
659
|
+
* @throws {@link ErrorCode|InternalError} when failed to login with unknown error.
|
|
660
|
+
* @throws {@link ErrorCode|ServiceError} when simple auth server failed to exchange access token.
|
|
661
|
+
* @throws {@link ErrorCode|ConsentFailed} when user canceled or failed to consent.
|
|
662
|
+
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
663
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
664
|
+
*
|
|
665
|
+
* @beta
|
|
666
|
+
*/
|
|
667
|
+
TeamsUserCredential.prototype.login = function (scopes) {
|
|
668
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
669
|
+
var scopesStr;
|
|
670
|
+
var _this = this;
|
|
671
|
+
return __generator(this, function (_a) {
|
|
672
|
+
validateScopesType(scopes);
|
|
673
|
+
scopesStr = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
674
|
+
internalLogger.info("Popup login page to get user's access token with scopes: " + scopesStr);
|
|
675
|
+
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
676
|
+
microsoftTeams.initialize(function () {
|
|
677
|
+
microsoftTeams.authentication.authenticate({
|
|
678
|
+
url: _this.config.initiateLoginEndpoint + "?clientId=" + _this.config.clientId + "&scope=" + encodeURI(scopesStr),
|
|
679
|
+
width: loginPageWidth,
|
|
680
|
+
height: loginPageHeight,
|
|
681
|
+
successCallback: function (result) { return __awaiter(_this, void 0, void 0, function () {
|
|
682
|
+
var errorMsg, authCodeResult, err_1;
|
|
683
|
+
return __generator(this, function (_a) {
|
|
684
|
+
switch (_a.label) {
|
|
685
|
+
case 0:
|
|
686
|
+
if (!result) {
|
|
687
|
+
errorMsg = "Get empty authentication result from Teams";
|
|
688
|
+
internalLogger.error(errorMsg);
|
|
689
|
+
reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
|
|
690
|
+
return [2 /*return*/];
|
|
691
|
+
}
|
|
692
|
+
authCodeResult = JSON.parse(result);
|
|
693
|
+
_a.label = 1;
|
|
694
|
+
case 1:
|
|
695
|
+
_a.trys.push([1, 3, , 4]);
|
|
696
|
+
return [4 /*yield*/, this.exchangeAccessTokenFromSimpleAuthServer(scopesStr, authCodeResult)];
|
|
697
|
+
case 2:
|
|
698
|
+
_a.sent();
|
|
699
|
+
resolve();
|
|
700
|
+
return [3 /*break*/, 4];
|
|
701
|
+
case 3:
|
|
702
|
+
err_1 = _a.sent();
|
|
703
|
+
reject(this.generateAuthServerError(err_1));
|
|
704
|
+
return [3 /*break*/, 4];
|
|
705
|
+
case 4: return [2 /*return*/];
|
|
706
|
+
}
|
|
707
|
+
});
|
|
708
|
+
}); },
|
|
709
|
+
failureCallback: function (reason) {
|
|
710
|
+
var errorMsg = "Consent failed for the scope " + scopesStr + " with error: " + reason;
|
|
711
|
+
internalLogger.error(errorMsg);
|
|
712
|
+
reject(new ErrorWithCode(errorMsg, ErrorCode.ConsentFailed));
|
|
713
|
+
},
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
})];
|
|
717
|
+
});
|
|
718
|
+
});
|
|
719
|
+
};
|
|
720
|
+
/**
|
|
721
|
+
* Get access token from credential.
|
|
722
|
+
*
|
|
723
|
+
* @example
|
|
724
|
+
* ```typescript
|
|
725
|
+
* await credential.getToken([]) // Get SSO token using empty string array
|
|
726
|
+
* await credential.getToken("") // Get SSO token using empty string
|
|
727
|
+
* await credential.getToken([".default"]) // Get Graph access token with default scope using string array
|
|
728
|
+
* await credential.getToken(".default") // Get Graph access token with default scope using string
|
|
729
|
+
* await credential.getToken(["User.Read"]) // Get Graph access token for single scope using string array
|
|
730
|
+
* await credential.getToken("User.Read") // Get Graph access token for single scope using string
|
|
731
|
+
* await credential.getToken(["User.Read", "Application.Read.All"]) // Get Graph access token for multiple scopes using string array
|
|
732
|
+
* await credential.getToken("User.Read Application.Read.All") // Get Graph access token for multiple scopes using space-separated string
|
|
733
|
+
* await credential.getToken("https://graph.microsoft.com/User.Read") // Get Graph access token with full resource URI
|
|
734
|
+
* await credential.getToken(["https://outlook.office.com/Mail.Read"]) // Get Outlook access token
|
|
735
|
+
* ```
|
|
736
|
+
*
|
|
737
|
+
* @param {string | string[]} scopes - The list of scopes for which the token will have access.
|
|
738
|
+
* @param {GetTokenOptions} options - The options used to configure any requests this TokenCredential implementation might make.
|
|
739
|
+
*
|
|
740
|
+
* @throws {@link ErrorCode|InternalError} when failed to get access token with unknown error.
|
|
741
|
+
* @throws {@link ErrorCode|UiRequiredError} when need user consent to get access token.
|
|
742
|
+
* @throws {@link ErrorCode|ServiceError} when failed to get access token from simple auth server.
|
|
743
|
+
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
744
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
745
|
+
*
|
|
746
|
+
* @returns User access token of defined scopes.
|
|
747
|
+
* If scopes is empty string or array, it returns SSO token.
|
|
748
|
+
* If scopes is non-empty, it returns access token for target scope.
|
|
749
|
+
* Throw error if get access token failed.
|
|
750
|
+
*
|
|
751
|
+
* @beta
|
|
752
|
+
*/
|
|
753
|
+
TeamsUserCredential.prototype.getToken = function (scopes, options) {
|
|
754
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
755
|
+
var ssoToken, scopeStr, cachedKey, cachedToken, accessToken;
|
|
756
|
+
return __generator(this, function (_a) {
|
|
757
|
+
switch (_a.label) {
|
|
758
|
+
case 0:
|
|
759
|
+
validateScopesType(scopes);
|
|
760
|
+
return [4 /*yield*/, this.getSSOToken()];
|
|
761
|
+
case 1:
|
|
762
|
+
ssoToken = _a.sent();
|
|
763
|
+
scopeStr = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
764
|
+
if (!(scopeStr === "")) return [3 /*break*/, 2];
|
|
765
|
+
internalLogger.info("Get SSO token");
|
|
766
|
+
return [2 /*return*/, ssoToken];
|
|
767
|
+
case 2:
|
|
768
|
+
internalLogger.info("Get access token with scopes: " + scopeStr);
|
|
769
|
+
return [4 /*yield*/, this.getAccessTokenCacheKey(scopeStr)];
|
|
770
|
+
case 3:
|
|
771
|
+
cachedKey = _a.sent();
|
|
772
|
+
cachedToken = this.getTokenCache(cachedKey);
|
|
773
|
+
if (cachedToken) {
|
|
774
|
+
if (!this.isAccessTokenNearExpired(cachedToken)) {
|
|
775
|
+
internalLogger.verbose("Get access token from cache");
|
|
776
|
+
return [2 /*return*/, cachedToken];
|
|
777
|
+
}
|
|
778
|
+
else {
|
|
779
|
+
internalLogger.verbose("Cached access token is expired");
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
else {
|
|
783
|
+
internalLogger.verbose("No cached access token");
|
|
784
|
+
}
|
|
785
|
+
return [4 /*yield*/, this.getAndCacheAccessTokenFromSimpleAuthServer(scopeStr)];
|
|
786
|
+
case 4:
|
|
787
|
+
accessToken = _a.sent();
|
|
788
|
+
return [2 /*return*/, accessToken];
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
});
|
|
792
|
+
};
|
|
793
|
+
/**
|
|
794
|
+
* Get basic user info from SSO token
|
|
795
|
+
*
|
|
796
|
+
* @example
|
|
797
|
+
* ```typescript
|
|
798
|
+
* const currentUser = await credential.getUserInfo();
|
|
799
|
+
* ```
|
|
800
|
+
*
|
|
801
|
+
* @throws {@link ErrorCode|InternalError} when SSO token from Teams client is not valid.
|
|
802
|
+
* @throws {@link ErrorCode|InvalidParameter} when SSO token from Teams client is empty.
|
|
803
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
804
|
+
*
|
|
805
|
+
* @returns Basic user info with user displayName, objectId and preferredUserName.
|
|
806
|
+
*
|
|
807
|
+
* @beta
|
|
808
|
+
*/
|
|
809
|
+
TeamsUserCredential.prototype.getUserInfo = function () {
|
|
810
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
811
|
+
var ssoToken;
|
|
812
|
+
return __generator(this, function (_a) {
|
|
813
|
+
switch (_a.label) {
|
|
814
|
+
case 0:
|
|
815
|
+
internalLogger.info("Get basic user info from SSO token");
|
|
816
|
+
return [4 /*yield*/, this.getSSOToken()];
|
|
817
|
+
case 1:
|
|
818
|
+
ssoToken = _a.sent();
|
|
819
|
+
return [2 /*return*/, getUserInfoFromSsoToken(ssoToken.token)];
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
});
|
|
823
|
+
};
|
|
824
|
+
TeamsUserCredential.prototype.exchangeAccessTokenFromSimpleAuthServer = function (scopesStr, authCodeResult) {
|
|
825
|
+
var _a, _b;
|
|
826
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
827
|
+
var axiosInstance, retryCount, response, tokenResult, key, err_2;
|
|
828
|
+
return __generator(this, function (_c) {
|
|
829
|
+
switch (_c.label) {
|
|
830
|
+
case 0: return [4 /*yield*/, this.getAxiosInstance()];
|
|
831
|
+
case 1:
|
|
832
|
+
axiosInstance = _c.sent();
|
|
833
|
+
retryCount = 0;
|
|
834
|
+
_c.label = 2;
|
|
835
|
+
case 2:
|
|
836
|
+
_c.label = 3;
|
|
837
|
+
case 3:
|
|
838
|
+
_c.trys.push([3, 6, , 9]);
|
|
839
|
+
return [4 /*yield*/, axiosInstance.post("/auth/token", {
|
|
840
|
+
scope: scopesStr,
|
|
841
|
+
code: authCodeResult.code,
|
|
842
|
+
code_verifier: authCodeResult.codeVerifier,
|
|
843
|
+
redirect_uri: authCodeResult.redirectUri,
|
|
844
|
+
grant_type: GrantType.authCode,
|
|
845
|
+
})];
|
|
846
|
+
case 4:
|
|
847
|
+
response = _c.sent();
|
|
848
|
+
tokenResult = response.data;
|
|
849
|
+
return [4 /*yield*/, this.getAccessTokenCacheKey(scopesStr)];
|
|
850
|
+
case 5:
|
|
851
|
+
key = _c.sent();
|
|
852
|
+
this.setTokenCache(key, {
|
|
853
|
+
token: tokenResult.access_token,
|
|
854
|
+
expiresOnTimestamp: tokenResult.expires_on,
|
|
855
|
+
});
|
|
856
|
+
return [2 /*return*/];
|
|
857
|
+
case 6:
|
|
858
|
+
err_2 = _c.sent();
|
|
859
|
+
if (!(((_b = (_a = err_2.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.type) && err_2.response.data.type === "AadUiRequiredException")) return [3 /*break*/, 8];
|
|
860
|
+
internalLogger.warn("Exchange access token failed, retry...");
|
|
861
|
+
if (!(retryCount < maxRetryCount)) return [3 /*break*/, 8];
|
|
862
|
+
return [4 /*yield*/, this.sleep(retryTimeSpanInMillisecond)];
|
|
863
|
+
case 7:
|
|
864
|
+
_c.sent();
|
|
865
|
+
retryCount++;
|
|
866
|
+
return [3 /*break*/, 2];
|
|
867
|
+
case 8: throw err_2;
|
|
868
|
+
case 9: return [3 /*break*/, 2];
|
|
869
|
+
case 10: return [2 /*return*/];
|
|
870
|
+
}
|
|
871
|
+
});
|
|
872
|
+
});
|
|
873
|
+
};
|
|
874
|
+
/**
|
|
875
|
+
* Get access token cache from authentication server
|
|
876
|
+
* @returns Access token
|
|
877
|
+
*/
|
|
878
|
+
TeamsUserCredential.prototype.getAndCacheAccessTokenFromSimpleAuthServer = function (scopesStr) {
|
|
879
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
880
|
+
var axiosInstance, response, accessTokenResult, accessToken, cacheKey, err_3;
|
|
881
|
+
return __generator(this, function (_a) {
|
|
882
|
+
switch (_a.label) {
|
|
883
|
+
case 0:
|
|
884
|
+
_a.trys.push([0, 4, , 5]);
|
|
885
|
+
internalLogger.verbose("Get access token from authentication server with scopes: " + scopesStr);
|
|
886
|
+
return [4 /*yield*/, this.getAxiosInstance()];
|
|
887
|
+
case 1:
|
|
888
|
+
axiosInstance = _a.sent();
|
|
889
|
+
return [4 /*yield*/, axiosInstance.post("/auth/token", {
|
|
890
|
+
scope: scopesStr,
|
|
891
|
+
grant_type: GrantType.ssoToken,
|
|
892
|
+
})];
|
|
893
|
+
case 2:
|
|
894
|
+
response = _a.sent();
|
|
895
|
+
accessTokenResult = response.data;
|
|
896
|
+
accessToken = {
|
|
897
|
+
token: accessTokenResult.access_token,
|
|
898
|
+
expiresOnTimestamp: accessTokenResult.expires_on,
|
|
899
|
+
};
|
|
900
|
+
return [4 /*yield*/, this.getAccessTokenCacheKey(scopesStr)];
|
|
901
|
+
case 3:
|
|
902
|
+
cacheKey = _a.sent();
|
|
903
|
+
this.setTokenCache(cacheKey, accessToken);
|
|
904
|
+
return [2 /*return*/, accessToken];
|
|
905
|
+
case 4:
|
|
906
|
+
err_3 = _a.sent();
|
|
907
|
+
throw this.generateAuthServerError(err_3);
|
|
908
|
+
case 5: return [2 /*return*/];
|
|
909
|
+
}
|
|
910
|
+
});
|
|
911
|
+
});
|
|
912
|
+
};
|
|
913
|
+
/**
|
|
914
|
+
* Get SSO token using teams SDK
|
|
915
|
+
* It will try to get SSO token from memory first, if SSO token doesn't exist or about to expired, then it will using teams SDK to get SSO token
|
|
916
|
+
* @returns SSO token
|
|
917
|
+
*/
|
|
918
|
+
TeamsUserCredential.prototype.getSSOToken = function () {
|
|
919
|
+
var _this = this;
|
|
920
|
+
return new Promise(function (resolve, reject) {
|
|
921
|
+
if (_this.ssoToken) {
|
|
922
|
+
if (_this.ssoToken.expiresOnTimestamp - Date.now() > tokenRefreshTimeSpanInMillisecond) {
|
|
923
|
+
internalLogger.verbose("Get SSO token from memory cache");
|
|
924
|
+
resolve(_this.ssoToken);
|
|
925
|
+
return;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
var initialized = false;
|
|
929
|
+
microsoftTeams.initialize(function () {
|
|
930
|
+
initialized = true;
|
|
931
|
+
microsoftTeams.authentication.getAuthToken({
|
|
932
|
+
successCallback: function (token) {
|
|
933
|
+
if (!token) {
|
|
934
|
+
var errorMsg = "Get empty SSO token from Teams";
|
|
935
|
+
internalLogger.error(errorMsg);
|
|
936
|
+
reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
939
|
+
var tokenObject = parseJwt(token);
|
|
940
|
+
if (tokenObject.ver !== "1.0" && tokenObject.ver !== "2.0") {
|
|
941
|
+
var errorMsg = "SSO token is not valid with an unknown version: " + tokenObject.ver;
|
|
942
|
+
internalLogger.error(errorMsg);
|
|
943
|
+
reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
|
|
944
|
+
return;
|
|
945
|
+
}
|
|
946
|
+
var ssoToken = {
|
|
947
|
+
token: token,
|
|
948
|
+
expiresOnTimestamp: tokenObject.exp * 1000,
|
|
949
|
+
};
|
|
950
|
+
_this.ssoToken = ssoToken;
|
|
951
|
+
resolve(ssoToken);
|
|
952
|
+
},
|
|
953
|
+
failureCallback: function (errMessage) {
|
|
954
|
+
var errorMsg = "Get SSO token failed with error: " + errMessage;
|
|
955
|
+
internalLogger.error(errorMsg);
|
|
956
|
+
reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
|
|
957
|
+
},
|
|
958
|
+
resources: [],
|
|
959
|
+
});
|
|
960
|
+
});
|
|
961
|
+
// If the code not running in Teams, the initialize callback function would never trigger
|
|
962
|
+
setTimeout(function () {
|
|
963
|
+
if (!initialized) {
|
|
964
|
+
var errorMsg = "Initialize teams sdk timeout, maybe the code is not running inside Teams";
|
|
965
|
+
internalLogger.error(errorMsg);
|
|
966
|
+
reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
|
|
967
|
+
}
|
|
968
|
+
}, initializeTeamsSdkTimeoutInMillisecond);
|
|
969
|
+
});
|
|
970
|
+
};
|
|
971
|
+
/**
|
|
972
|
+
* Load and validate authentication configuration
|
|
973
|
+
* @returns Authentication configuration
|
|
974
|
+
*/
|
|
975
|
+
TeamsUserCredential.prototype.loadAndValidateConfig = function () {
|
|
976
|
+
internalLogger.verbose("Validate authentication configuration");
|
|
977
|
+
var config = getAuthenticationConfiguration();
|
|
978
|
+
if (!config) {
|
|
979
|
+
internalLogger.error(ErrorMessage.AuthenticationConfigurationNotExists);
|
|
980
|
+
throw new ErrorWithCode(ErrorMessage.AuthenticationConfigurationNotExists, ErrorCode.InvalidConfiguration);
|
|
981
|
+
}
|
|
982
|
+
if (config.initiateLoginEndpoint && config.simpleAuthEndpoint && config.clientId) {
|
|
983
|
+
return config;
|
|
984
|
+
}
|
|
985
|
+
var missingValues = [];
|
|
986
|
+
if (!config.initiateLoginEndpoint) {
|
|
987
|
+
missingValues.push("initiateLoginEndpoint");
|
|
988
|
+
}
|
|
989
|
+
if (!config.simpleAuthEndpoint) {
|
|
990
|
+
missingValues.push("simpleAuthEndpoint");
|
|
991
|
+
}
|
|
992
|
+
if (!config.clientId) {
|
|
993
|
+
missingValues.push("clientId");
|
|
994
|
+
}
|
|
995
|
+
var errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingValues.join(", "), "undefined");
|
|
996
|
+
internalLogger.error(errorMsg);
|
|
997
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);
|
|
998
|
+
};
|
|
999
|
+
/**
|
|
1000
|
+
* Get axios instance with sso token bearer header
|
|
1001
|
+
* @returns AxiosInstance
|
|
1002
|
+
*/
|
|
1003
|
+
TeamsUserCredential.prototype.getAxiosInstance = function () {
|
|
1004
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1005
|
+
var ssoToken, axiosInstance;
|
|
1006
|
+
return __generator(this, function (_a) {
|
|
1007
|
+
switch (_a.label) {
|
|
1008
|
+
case 0: return [4 /*yield*/, this.getSSOToken()];
|
|
1009
|
+
case 1:
|
|
1010
|
+
ssoToken = _a.sent();
|
|
1011
|
+
axiosInstance = axios.create({
|
|
1012
|
+
baseURL: this.config.simpleAuthEndpoint,
|
|
1013
|
+
});
|
|
1014
|
+
axiosInstance.interceptors.request.use(function (config) {
|
|
1015
|
+
config.headers.Authorization = "Bearer " + ssoToken.token;
|
|
1016
|
+
return config;
|
|
1017
|
+
});
|
|
1018
|
+
return [2 /*return*/, axiosInstance];
|
|
1019
|
+
}
|
|
1020
|
+
});
|
|
1021
|
+
});
|
|
1022
|
+
};
|
|
1023
|
+
/**
|
|
1024
|
+
* Set access token to cache
|
|
1025
|
+
* @param key
|
|
1026
|
+
* @param token
|
|
1027
|
+
*/
|
|
1028
|
+
TeamsUserCredential.prototype.setTokenCache = function (key, token) {
|
|
1029
|
+
Cache.set(key, JSON.stringify(token));
|
|
1030
|
+
};
|
|
1031
|
+
/**
|
|
1032
|
+
* Get access token from cache.
|
|
1033
|
+
* If there is no cache or cannot be parsed, then it will return null
|
|
1034
|
+
* @param key
|
|
1035
|
+
* @returns Access token or null
|
|
1036
|
+
*/
|
|
1037
|
+
TeamsUserCredential.prototype.getTokenCache = function (key) {
|
|
1038
|
+
var value = Cache.get(key);
|
|
1039
|
+
if (value === null) {
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
1042
|
+
var accessToken = this.validateAndParseJson(value);
|
|
1043
|
+
return accessToken;
|
|
1044
|
+
};
|
|
1045
|
+
/**
|
|
1046
|
+
* Parses passed value as JSON access token, if value is not a valid json string JSON.parse() will throw an error.
|
|
1047
|
+
* @param jsonValue
|
|
1048
|
+
*/
|
|
1049
|
+
TeamsUserCredential.prototype.validateAndParseJson = function (jsonValue) {
|
|
1050
|
+
try {
|
|
1051
|
+
var parsedJson = JSON.parse(jsonValue);
|
|
1052
|
+
/**
|
|
1053
|
+
* There are edge cases in which JSON.parse will successfully parse a non-valid JSON object
|
|
1054
|
+
* (e.g. JSON.parse will parse an escaped string into an unescaped string), so adding a type check
|
|
1055
|
+
* of the parsed value is necessary in order to be certain that the string represents a valid JSON object.
|
|
1056
|
+
*
|
|
1057
|
+
*/
|
|
1058
|
+
return parsedJson && typeof parsedJson === "object" ? parsedJson : null;
|
|
1059
|
+
}
|
|
1060
|
+
catch (error) {
|
|
1061
|
+
return null;
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
/**
|
|
1065
|
+
* Generate cache key
|
|
1066
|
+
* @param scopesStr
|
|
1067
|
+
* @returns Access token cache key, a key example: accessToken-userId-clientId-tenantId-scopes
|
|
1068
|
+
*/
|
|
1069
|
+
TeamsUserCredential.prototype.getAccessTokenCacheKey = function (scopesStr) {
|
|
1070
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1071
|
+
var ssoToken, ssoTokenObj, clientId, userObjectId, tenantId, key;
|
|
1072
|
+
return __generator(this, function (_a) {
|
|
1073
|
+
switch (_a.label) {
|
|
1074
|
+
case 0: return [4 /*yield*/, this.getSSOToken()];
|
|
1075
|
+
case 1:
|
|
1076
|
+
ssoToken = _a.sent();
|
|
1077
|
+
ssoTokenObj = parseJwt(ssoToken.token);
|
|
1078
|
+
clientId = this.config.clientId;
|
|
1079
|
+
userObjectId = ssoTokenObj.oid;
|
|
1080
|
+
tenantId = ssoTokenObj.tid;
|
|
1081
|
+
key = [accessTokenCacheKeyPrefix, userObjectId, clientId, tenantId, scopesStr]
|
|
1082
|
+
.join(separator)
|
|
1083
|
+
.replace(/" "/g, "_");
|
|
1084
|
+
return [2 /*return*/, key];
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
1087
|
+
});
|
|
1088
|
+
};
|
|
1089
|
+
/**
|
|
1090
|
+
* Check whether the token is about to expire (within 5 minutes)
|
|
1091
|
+
* @returns Boolean value indicate whether the token is about to expire
|
|
1092
|
+
*/
|
|
1093
|
+
TeamsUserCredential.prototype.isAccessTokenNearExpired = function (token) {
|
|
1094
|
+
var expireDate = new Date(token.expiresOnTimestamp);
|
|
1095
|
+
if (expireDate.getTime() - Date.now() > tokenRefreshTimeSpanInMillisecond) {
|
|
1096
|
+
return false;
|
|
1097
|
+
}
|
|
1098
|
+
return true;
|
|
1099
|
+
};
|
|
1100
|
+
TeamsUserCredential.prototype.generateAuthServerError = function (err) {
|
|
1101
|
+
var _a, _b;
|
|
1102
|
+
var errorMessage = err.message;
|
|
1103
|
+
if ((_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.type) {
|
|
1104
|
+
errorMessage = err.response.data.detail;
|
|
1105
|
+
if (err.response.data.type === "AadUiRequiredException") {
|
|
1106
|
+
var fullErrorMsg_1 = "Failed to get access token from authentication server, please login first: " +
|
|
1107
|
+
errorMessage;
|
|
1108
|
+
internalLogger.warn(fullErrorMsg_1);
|
|
1109
|
+
return new ErrorWithCode(fullErrorMsg_1, ErrorCode.UiRequiredError);
|
|
1110
|
+
}
|
|
1111
|
+
else {
|
|
1112
|
+
var fullErrorMsg_2 = "Failed to get access token from authentication server: " + errorMessage;
|
|
1113
|
+
internalLogger.error(fullErrorMsg_2);
|
|
1114
|
+
return new ErrorWithCode(fullErrorMsg_2, ErrorCode.ServiceError);
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
var fullErrorMsg = "Failed to get access token with error: " + errorMessage;
|
|
1118
|
+
return new ErrorWithCode(fullErrorMsg, ErrorCode.InternalError);
|
|
1119
|
+
};
|
|
1120
|
+
TeamsUserCredential.prototype.sleep = function (ms) {
|
|
1121
|
+
return new Promise(function (resolve) { return setTimeout(resolve, ms); });
|
|
1122
|
+
};
|
|
1123
|
+
return TeamsUserCredential;
|
|
1124
|
+
}());
|
|
1125
|
+
|
|
1126
|
+
// Copyright (c) Microsoft Corporation.
|
|
1127
|
+
var defaultScope = "https://graph.microsoft.com/.default";
|
|
1128
|
+
/**
|
|
1129
|
+
* Microsoft Graph auth provider for Teams Framework
|
|
1130
|
+
*
|
|
1131
|
+
* @beta
|
|
1132
|
+
*/
|
|
1133
|
+
var MsGraphAuthProvider = /** @class */ (function () {
|
|
1134
|
+
/**
|
|
1135
|
+
* Constructor of MsGraphAuthProvider.
|
|
1136
|
+
*
|
|
1137
|
+
* @param {TokenCredential} credential - Credential used to invoke Microsoft Graph APIs.
|
|
1138
|
+
* @param {string | string[]} scopes - The list of scopes for which the token will have access.
|
|
1139
|
+
*
|
|
1140
|
+
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
1141
|
+
*
|
|
1142
|
+
* @returns An instance of MsGraphAuthProvider.
|
|
1143
|
+
*
|
|
1144
|
+
* @beta
|
|
1145
|
+
*/
|
|
1146
|
+
function MsGraphAuthProvider(credential, scopes) {
|
|
1147
|
+
this.credential = credential;
|
|
1148
|
+
var scopesStr = defaultScope;
|
|
1149
|
+
if (scopes) {
|
|
1150
|
+
validateScopesType(scopes);
|
|
1151
|
+
scopesStr = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
1152
|
+
if (scopesStr === "") {
|
|
1153
|
+
scopesStr = defaultScope;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
internalLogger.info("Create Microsoft Graph Authentication Provider with scopes: '" + scopesStr + "'");
|
|
1157
|
+
this.scopes = scopesStr;
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Get access token for Microsoft Graph API requests.
|
|
1161
|
+
*
|
|
1162
|
+
* @throws {@link ErrorCode|InternalError} when get access token failed due to empty token or unknown other problems.
|
|
1163
|
+
* @throws {@link ErrorCode|TokenExpiredError} when SSO token has already expired.
|
|
1164
|
+
* @throws {@link ErrorCode|UiRequiredError} when need user consent to get access token.
|
|
1165
|
+
* @throws {@link ErrorCode|ServiceError} when failed to get access token from simple auth or AAD server.
|
|
1166
|
+
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
1167
|
+
*
|
|
1168
|
+
* @returns Access token from the credential.
|
|
1169
|
+
*
|
|
1170
|
+
*/
|
|
1171
|
+
MsGraphAuthProvider.prototype.getAccessToken = function () {
|
|
1172
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1173
|
+
var accessToken;
|
|
1174
|
+
return __generator(this, function (_a) {
|
|
1175
|
+
switch (_a.label) {
|
|
1176
|
+
case 0:
|
|
1177
|
+
internalLogger.info("Get Graph Access token with scopes: '" + this.scopes + "'");
|
|
1178
|
+
return [4 /*yield*/, this.credential.getToken(this.scopes)];
|
|
1179
|
+
case 1:
|
|
1180
|
+
accessToken = _a.sent();
|
|
1181
|
+
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
1182
|
+
if (accessToken) {
|
|
1183
|
+
resolve(accessToken.token);
|
|
1184
|
+
}
|
|
1185
|
+
else {
|
|
1186
|
+
var errorMsg = "Graph access token is undefined or empty";
|
|
1187
|
+
internalLogger.error(errorMsg);
|
|
1188
|
+
reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
|
|
1189
|
+
}
|
|
1190
|
+
})];
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
1193
|
+
});
|
|
1194
|
+
};
|
|
1195
|
+
return MsGraphAuthProvider;
|
|
1196
|
+
}());
|
|
1197
|
+
|
|
1198
|
+
// Copyright (c) Microsoft Corporation.
|
|
1199
|
+
/**
|
|
1200
|
+
* Get Microsoft graph client.
|
|
1201
|
+
*
|
|
1202
|
+
* @example
|
|
1203
|
+
* Get Microsoft graph client by TokenCredential
|
|
1204
|
+
* ```typescript
|
|
1205
|
+
* // Sso token example (Azure Function)
|
|
1206
|
+
* const ssoToken = "YOUR_TOKEN_STRING";
|
|
1207
|
+
* const options = {"AAD_APP_ID", "AAD_APP_SECRET"};
|
|
1208
|
+
* const credential = new OnBehalfOfAADUserCredential(ssoToken, options);
|
|
1209
|
+
* const graphClient = await createMicrosoftGraphClient(credential);
|
|
1210
|
+
* const profile = await graphClient.api("/me").get();
|
|
1211
|
+
*
|
|
1212
|
+
* // TeamsBotSsoPrompt example (Bot Application)
|
|
1213
|
+
* const requiredScopes = ["User.Read"];
|
|
1214
|
+
* const config: Configuration = {
|
|
1215
|
+
* loginUrl: loginUrl,
|
|
1216
|
+
* clientId: clientId,
|
|
1217
|
+
* clientSecret: clientSecret,
|
|
1218
|
+
* tenantId: tenantId
|
|
1219
|
+
* };
|
|
1220
|
+
* const prompt = new TeamsBotSsoPrompt(dialogId, {
|
|
1221
|
+
* config: config
|
|
1222
|
+
* scopes: '["User.Read"],
|
|
1223
|
+
* });
|
|
1224
|
+
* this.addDialog(prompt);
|
|
1225
|
+
*
|
|
1226
|
+
* const oboCredential = new OnBehalfOfAADUserCredential(
|
|
1227
|
+
* getUserId(dialogContext),
|
|
1228
|
+
* {
|
|
1229
|
+
* clientId: "AAD_APP_ID",
|
|
1230
|
+
* clientSecret: "AAD_APP_SECRET"
|
|
1231
|
+
* });
|
|
1232
|
+
* try {
|
|
1233
|
+
* const graphClient = await createMicrosoftGraphClient(credential);
|
|
1234
|
+
* const profile = await graphClient.api("/me").get();
|
|
1235
|
+
* } catch (e) {
|
|
1236
|
+
* dialogContext.beginDialog(dialogId);
|
|
1237
|
+
* return Dialog.endOfTurn();
|
|
1238
|
+
* }
|
|
1239
|
+
* ```
|
|
1240
|
+
*
|
|
1241
|
+
* @param {TokenCredential} credential - token credential instance.
|
|
1242
|
+
* @param scopes - The array of Microsoft Token scope of access. Default value is `[.default]`.
|
|
1243
|
+
*
|
|
1244
|
+
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
1245
|
+
*
|
|
1246
|
+
* @returns Graph client with specified scopes.
|
|
1247
|
+
*
|
|
1248
|
+
* @beta
|
|
1249
|
+
*/
|
|
1250
|
+
function createMicrosoftGraphClient(credential, scopes) {
|
|
1251
|
+
internalLogger.info("Create Microsoft Graph Client");
|
|
1252
|
+
var authProvider = new MsGraphAuthProvider(credential, scopes);
|
|
1253
|
+
var graphClient = Client.initWithMiddleware({
|
|
1254
|
+
authProvider: authProvider,
|
|
1255
|
+
});
|
|
1256
|
+
return graphClient;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
// Copyright (c) Microsoft Corporation.
|
|
1260
|
+
/**
|
|
1261
|
+
* SQL connection configuration instance.
|
|
1262
|
+
* @remarks
|
|
1263
|
+
* Only works in in server side.
|
|
1264
|
+
*
|
|
1265
|
+
* @beta
|
|
1266
|
+
*
|
|
1267
|
+
*/
|
|
1268
|
+
var DefaultTediousConnectionConfiguration = /** @class */ (function () {
|
|
1269
|
+
function DefaultTediousConnectionConfiguration() {
|
|
1270
|
+
/**
|
|
1271
|
+
* MSSQL default scope
|
|
1272
|
+
* https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi
|
|
1273
|
+
*/
|
|
1274
|
+
this.defaultSQLScope = "https://database.windows.net/";
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Generate connection configuration consumed by tedious.
|
|
1278
|
+
*
|
|
1279
|
+
* @returns Connection configuration of tedious for the SQL.
|
|
1280
|
+
*
|
|
1281
|
+
* @throws {@link ErrorCode|InvalidConfiguration} when SQL config resource configuration is invalid.
|
|
1282
|
+
* @throws {@link ErrorCode|InternalError} when get user MSI token failed or MSI token is invalid.
|
|
1283
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
1284
|
+
*
|
|
1285
|
+
* @beta
|
|
1286
|
+
*/
|
|
1287
|
+
DefaultTediousConnectionConfiguration.prototype.getConfig = function () {
|
|
1288
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1289
|
+
var configuration, errMsg, configWithUPS, configWithToken, error_1;
|
|
1290
|
+
return __generator(this, function (_a) {
|
|
1291
|
+
switch (_a.label) {
|
|
1292
|
+
case 0:
|
|
1293
|
+
internalLogger.info("Get SQL configuration");
|
|
1294
|
+
configuration = getResourceConfiguration(ResourceType.SQL);
|
|
1295
|
+
if (!configuration) {
|
|
1296
|
+
errMsg = "SQL resource configuration not exist";
|
|
1297
|
+
internalLogger.error(errMsg);
|
|
1298
|
+
throw new ErrorWithCode(errMsg, ErrorCode.InvalidConfiguration);
|
|
1299
|
+
}
|
|
1300
|
+
try {
|
|
1301
|
+
this.isSQLConfigurationValid(configuration);
|
|
1302
|
+
}
|
|
1303
|
+
catch (err) {
|
|
1304
|
+
throw err;
|
|
1305
|
+
}
|
|
1306
|
+
if (!this.isMsiAuthentication()) {
|
|
1307
|
+
configWithUPS = this.generateDefaultConfig(configuration);
|
|
1308
|
+
internalLogger.verbose("SQL configuration with username and password generated");
|
|
1309
|
+
return [2 /*return*/, configWithUPS];
|
|
1310
|
+
}
|
|
1311
|
+
_a.label = 1;
|
|
1312
|
+
case 1:
|
|
1313
|
+
_a.trys.push([1, 3, , 4]);
|
|
1314
|
+
return [4 /*yield*/, this.generateTokenConfig(configuration)];
|
|
1315
|
+
case 2:
|
|
1316
|
+
configWithToken = _a.sent();
|
|
1317
|
+
internalLogger.verbose("SQL configuration with MSI token generated");
|
|
1318
|
+
return [2 /*return*/, configWithToken];
|
|
1319
|
+
case 3:
|
|
1320
|
+
error_1 = _a.sent();
|
|
1321
|
+
throw error_1;
|
|
1322
|
+
case 4: return [2 /*return*/];
|
|
1323
|
+
}
|
|
1324
|
+
});
|
|
1325
|
+
});
|
|
1326
|
+
};
|
|
1327
|
+
/**
|
|
1328
|
+
* Check SQL use MSI identity or username and password.
|
|
1329
|
+
*
|
|
1330
|
+
* @returns false - login with SQL MSI identity, true - login with username and password.
|
|
1331
|
+
* @internal
|
|
1332
|
+
*/
|
|
1333
|
+
DefaultTediousConnectionConfiguration.prototype.isMsiAuthentication = function () {
|
|
1334
|
+
internalLogger.verbose("Check connection config using MSI access token or username and password");
|
|
1335
|
+
var configuration = getResourceConfiguration(ResourceType.SQL);
|
|
1336
|
+
if ((configuration === null || configuration === void 0 ? void 0 : configuration.sqlUsername) != null && (configuration === null || configuration === void 0 ? void 0 : configuration.sqlPassword) != null) {
|
|
1337
|
+
internalLogger.verbose("Login with username and password");
|
|
1338
|
+
return false;
|
|
1339
|
+
}
|
|
1340
|
+
internalLogger.verbose("Login with MSI identity");
|
|
1341
|
+
return true;
|
|
1342
|
+
};
|
|
1343
|
+
/**
|
|
1344
|
+
* check configuration is an available configurations.
|
|
1345
|
+
* @param { SqlConfiguration } sqlConfig
|
|
1346
|
+
*
|
|
1347
|
+
* @returns true - SQL configuration has a valid SQL endpoints, SQL username with password or identity ID.
|
|
1348
|
+
* false - configuration is not valid.
|
|
1349
|
+
* @internal
|
|
1350
|
+
*/
|
|
1351
|
+
DefaultTediousConnectionConfiguration.prototype.isSQLConfigurationValid = function (sqlConfig) {
|
|
1352
|
+
internalLogger.verbose("Check SQL configuration if valid");
|
|
1353
|
+
if (!sqlConfig.sqlServerEndpoint) {
|
|
1354
|
+
internalLogger.error("SQL configuration is not valid without SQL server endpoint exist");
|
|
1355
|
+
throw new ErrorWithCode("SQL configuration error without SQL server endpoint exist", ErrorCode.InvalidConfiguration);
|
|
1356
|
+
}
|
|
1357
|
+
if (!(sqlConfig.sqlUsername && sqlConfig.sqlPassword) && !sqlConfig.sqlIdentityId) {
|
|
1358
|
+
var errMsg = "SQL configuration is not valid without " + (sqlConfig.sqlIdentityId ? "" : "identity id ") + " " + (sqlConfig.sqlUsername ? "" : "SQL username ") + " " + (sqlConfig.sqlPassword ? "" : "SQL password") + " exist";
|
|
1359
|
+
internalLogger.error(errMsg);
|
|
1360
|
+
throw new ErrorWithCode(errMsg, ErrorCode.InvalidConfiguration);
|
|
1361
|
+
}
|
|
1362
|
+
internalLogger.verbose("SQL configuration is valid");
|
|
1363
|
+
};
|
|
1364
|
+
/**
|
|
1365
|
+
* Generate tedious connection configuration with default authentication type.
|
|
1366
|
+
*
|
|
1367
|
+
* @param { SqlConfiguration } SQL configuration with username and password.
|
|
1368
|
+
*
|
|
1369
|
+
* @returns Tedious connection configuration with username and password.
|
|
1370
|
+
* @internal
|
|
1371
|
+
*/
|
|
1372
|
+
DefaultTediousConnectionConfiguration.prototype.generateDefaultConfig = function (sqlConfig) {
|
|
1373
|
+
internalLogger.verbose("SQL server " + sqlConfig.sqlServerEndpoint + ", user name " + sqlConfig.sqlUsername + ", database name " + sqlConfig.sqlDatabaseName);
|
|
1374
|
+
var config = {
|
|
1375
|
+
server: sqlConfig.sqlServerEndpoint,
|
|
1376
|
+
authentication: {
|
|
1377
|
+
type: TediousAuthenticationType.default,
|
|
1378
|
+
options: {
|
|
1379
|
+
userName: sqlConfig.sqlUsername,
|
|
1380
|
+
password: sqlConfig.sqlPassword,
|
|
1381
|
+
},
|
|
1382
|
+
},
|
|
1383
|
+
options: {
|
|
1384
|
+
database: sqlConfig.sqlDatabaseName,
|
|
1385
|
+
encrypt: true,
|
|
1386
|
+
},
|
|
1387
|
+
};
|
|
1388
|
+
return config;
|
|
1389
|
+
};
|
|
1390
|
+
/**
|
|
1391
|
+
* Generate tedious connection configuration with azure-active-directory-access-token authentication type.
|
|
1392
|
+
*
|
|
1393
|
+
* @param { SqlConfiguration } SQL configuration with AAD access token.
|
|
1394
|
+
*
|
|
1395
|
+
* @returns Tedious connection configuration with access token.
|
|
1396
|
+
* @internal
|
|
1397
|
+
*/
|
|
1398
|
+
DefaultTediousConnectionConfiguration.prototype.generateTokenConfig = function (sqlConfig) {
|
|
1399
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1400
|
+
var token, credential, errMsg, config;
|
|
1401
|
+
return __generator(this, function (_a) {
|
|
1402
|
+
switch (_a.label) {
|
|
1403
|
+
case 0:
|
|
1404
|
+
internalLogger.verbose("Generate tedious config with MSI token");
|
|
1405
|
+
_a.label = 1;
|
|
1406
|
+
case 1:
|
|
1407
|
+
_a.trys.push([1, 3, , 4]);
|
|
1408
|
+
credential = new ManagedIdentityCredential(sqlConfig.sqlIdentityId);
|
|
1409
|
+
return [4 /*yield*/, credential.getToken(this.defaultSQLScope)];
|
|
1410
|
+
case 2:
|
|
1411
|
+
token = _a.sent();
|
|
1412
|
+
return [3 /*break*/, 4];
|
|
1413
|
+
case 3:
|
|
1414
|
+
_a.sent();
|
|
1415
|
+
errMsg = "Get user MSI token failed";
|
|
1416
|
+
internalLogger.error(errMsg);
|
|
1417
|
+
throw new ErrorWithCode(errMsg, ErrorCode.InternalError);
|
|
1418
|
+
case 4:
|
|
1419
|
+
if (token) {
|
|
1420
|
+
config = {
|
|
1421
|
+
server: sqlConfig.sqlServerEndpoint,
|
|
1422
|
+
authentication: {
|
|
1423
|
+
type: TediousAuthenticationType.MSI,
|
|
1424
|
+
options: {
|
|
1425
|
+
token: token.token,
|
|
1426
|
+
},
|
|
1427
|
+
},
|
|
1428
|
+
options: {
|
|
1429
|
+
database: sqlConfig.sqlDatabaseName,
|
|
1430
|
+
encrypt: true,
|
|
1431
|
+
},
|
|
1432
|
+
};
|
|
1433
|
+
internalLogger.verbose("Generate token configuration success, server endpoint is " + sqlConfig.sqlServerEndpoint + ", database name is " + sqlConfig.sqlDatabaseName);
|
|
1434
|
+
return [2 /*return*/, config];
|
|
1435
|
+
}
|
|
1436
|
+
internalLogger.error("Generate token configuration, server endpoint is " + sqlConfig.sqlServerEndpoint + ", MSI token is not valid");
|
|
1437
|
+
throw new ErrorWithCode("MSI token is not valid", ErrorCode.InternalError);
|
|
1438
|
+
}
|
|
1439
|
+
});
|
|
1440
|
+
});
|
|
1441
|
+
};
|
|
1442
|
+
return DefaultTediousConnectionConfiguration;
|
|
1443
|
+
}());
|
|
1444
|
+
/**
|
|
1445
|
+
* tedious connection config authentication type.
|
|
1446
|
+
* https://tediousjs.github.io/tedious/api-connection.html
|
|
1447
|
+
* @internal
|
|
1448
|
+
*/
|
|
1449
|
+
var TediousAuthenticationType;
|
|
1450
|
+
(function (TediousAuthenticationType) {
|
|
1451
|
+
TediousAuthenticationType["default"] = "default";
|
|
1452
|
+
TediousAuthenticationType["MSI"] = "azure-active-directory-access-token";
|
|
1453
|
+
})(TediousAuthenticationType || (TediousAuthenticationType = {}));
|
|
1454
|
+
|
|
1455
|
+
// Copyright (c) Microsoft Corporation.
|
|
1456
|
+
/**
|
|
1457
|
+
* Creates a new prompt that leverage Teams Single Sign On (SSO) support for bot to automatically sign in user and
|
|
1458
|
+
* help receive oauth token, asks the user to consent if needed.
|
|
1459
|
+
*
|
|
1460
|
+
* @remarks
|
|
1461
|
+
* The prompt will attempt to retrieve the users current token of the desired scopes and store it in
|
|
1462
|
+
* the token store.
|
|
1463
|
+
*
|
|
1464
|
+
* User will be automatically signed in leveraging Teams support of Bot Single Sign On(SSO):
|
|
1465
|
+
* https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/auth-aad-sso-bots
|
|
1466
|
+
*
|
|
1467
|
+
* @example
|
|
1468
|
+
* When used with your bots `DialogSet` you can simply add a new instance of the prompt as a named
|
|
1469
|
+
* dialog using `DialogSet.add()`. You can then start the prompt from a waterfall step using either
|
|
1470
|
+
* `DialogContext.beginDialog()` or `DialogContext.prompt()`. The user will be prompted to sign in as
|
|
1471
|
+
* needed and their access token will be passed as an argument to the callers next waterfall step:
|
|
1472
|
+
*
|
|
1473
|
+
* ```JavaScript
|
|
1474
|
+
* const { ConversationState, MemoryStorage } = require('botbuilder');
|
|
1475
|
+
* const { DialogSet, WaterfallDialog } = require('botbuilder-dialogs');
|
|
1476
|
+
* const { TeamsBotSsoPrompt } = require('@microsoft/teamsfx');
|
|
1477
|
+
*
|
|
1478
|
+
* const convoState = new ConversationState(new MemoryStorage());
|
|
1479
|
+
* const dialogState = convoState.createProperty('dialogState');
|
|
1480
|
+
* const dialogs = new DialogSet(dialogState);
|
|
1481
|
+
*
|
|
1482
|
+
* loadConfiguration();
|
|
1483
|
+
* dialogs.add(new TeamsBotSsoPrompt('TeamsBotSsoPrompt', {
|
|
1484
|
+
* scopes: ["User.Read"],
|
|
1485
|
+
* }));
|
|
1486
|
+
*
|
|
1487
|
+
* dialogs.add(new WaterfallDialog('taskNeedingLogin', [
|
|
1488
|
+
* async (step) => {
|
|
1489
|
+
* return await step.beginDialog('TeamsBotSsoPrompt');
|
|
1490
|
+
* },
|
|
1491
|
+
* async (step) => {
|
|
1492
|
+
* const token = step.result;
|
|
1493
|
+
* if (token) {
|
|
1494
|
+
*
|
|
1495
|
+
* // ... continue with task needing access token ...
|
|
1496
|
+
*
|
|
1497
|
+
* } else {
|
|
1498
|
+
* await step.context.sendActivity(`Sorry... We couldn't log you in. Try again later.`);
|
|
1499
|
+
* return await step.endDialog();
|
|
1500
|
+
* }
|
|
1501
|
+
* }
|
|
1502
|
+
* ]));
|
|
1503
|
+
* ```
|
|
1504
|
+
*
|
|
1505
|
+
* @beta
|
|
1506
|
+
*/
|
|
1507
|
+
var TeamsBotSsoPrompt = /** @class */ (function () {
|
|
1508
|
+
/**
|
|
1509
|
+
* Constructor of TeamsBotSsoPrompt.
|
|
1510
|
+
*
|
|
1511
|
+
* @param dialogId Unique ID of the dialog within its parent `DialogSet` or `ComponentDialog`.
|
|
1512
|
+
* @param settings Settings used to configure the prompt.
|
|
1513
|
+
*
|
|
1514
|
+
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
1515
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
1516
|
+
*
|
|
1517
|
+
* @beta
|
|
1518
|
+
*/
|
|
1519
|
+
function TeamsBotSsoPrompt(dialogId, settings) {
|
|
1520
|
+
this.settings = settings;
|
|
1521
|
+
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "TeamsBotSsoPrompt"), ErrorCode.RuntimeNotSupported);
|
|
1522
|
+
}
|
|
1523
|
+
/**
|
|
1524
|
+
* Called when a prompt dialog is pushed onto the dialog stack and is being activated.
|
|
1525
|
+
* @remarks
|
|
1526
|
+
* If the task is successful, the result indicates whether the prompt is still
|
|
1527
|
+
* active after the turn has been processed by the prompt.
|
|
1528
|
+
*
|
|
1529
|
+
* @param dc The DialogContext for the current turn of the conversation.
|
|
1530
|
+
*
|
|
1531
|
+
* @throws {@link ErrorCode|InvalidParameter} when timeout property in teams bot sso prompt settings is not number or is not positive.
|
|
1532
|
+
* @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.
|
|
1533
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
1534
|
+
*
|
|
1535
|
+
* @returns A `Promise` representing the asynchronous operation.
|
|
1536
|
+
*
|
|
1537
|
+
* @beta
|
|
1538
|
+
*/
|
|
1539
|
+
TeamsBotSsoPrompt.prototype.beginDialog = function (dc) {
|
|
1540
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1541
|
+
return __generator(this, function (_a) {
|
|
1542
|
+
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "TeamsBotSsoPrompt"), ErrorCode.RuntimeNotSupported);
|
|
1543
|
+
});
|
|
1544
|
+
});
|
|
1545
|
+
};
|
|
1546
|
+
/**
|
|
1547
|
+
* Called when a prompt dialog is the active dialog and the user replied with a new activity.
|
|
1548
|
+
*
|
|
1549
|
+
* @remarks
|
|
1550
|
+
* If the task is successful, the result indicates whether the dialog is still
|
|
1551
|
+
* active after the turn has been processed by the dialog.
|
|
1552
|
+
* The prompt generally continues to receive the user's replies until it accepts the
|
|
1553
|
+
* user's reply as valid input for the prompt.
|
|
1554
|
+
*
|
|
1555
|
+
* @param dc The DialogContext for the current turn of the conversation.
|
|
1556
|
+
*
|
|
1557
|
+
* @returns A `Promise` representing the asynchronous operation.
|
|
1558
|
+
*
|
|
1559
|
+
* @throws {@link ErrorCode|ChannelNotSupported} when bot channel is not MS Teams.
|
|
1560
|
+
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
1561
|
+
*
|
|
1562
|
+
* @beta
|
|
1563
|
+
*/
|
|
1564
|
+
TeamsBotSsoPrompt.prototype.continueDialog = function (dc) {
|
|
1565
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1566
|
+
return __generator(this, function (_a) {
|
|
1567
|
+
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "TeamsBotSsoPrompt"), ErrorCode.RuntimeNotSupported);
|
|
1568
|
+
});
|
|
1569
|
+
});
|
|
1570
|
+
};
|
|
1571
|
+
return TeamsBotSsoPrompt;
|
|
1572
|
+
}());
|
|
1573
|
+
|
|
1574
|
+
export { DefaultTediousConnectionConfiguration, ErrorCode, ErrorWithCode, LogLevel, M365TenantCredential, MsGraphAuthProvider, OnBehalfOfUserCredential, ResourceType, TeamsBotSsoPrompt, TeamsUserCredential, createMicrosoftGraphClient, getAuthenticationConfiguration, getLogLevel, getResourceConfiguration, loadConfiguration, setLogFunction, setLogLevel, setLogger };
|
|
1575
|
+
//# sourceMappingURL=index.esm5.js.map
|