@microsoft/teamsfx 0.4.2-alpha.eb4575da.0 → 0.5.1-alpha.70b3a70e.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 +3 -4
- package/dist/index.esm2017.js +39 -4
- package/dist/index.esm2017.js.map +1 -1
- package/dist/index.esm2017.mjs +22 -9
- package/dist/index.esm2017.mjs.map +1 -1
- package/dist/index.esm5.js +312 -362
- package/dist/index.esm5.js.map +1 -1
- package/dist/index.node.cjs.js +442 -546
- package/dist/index.node.cjs.js.map +1 -1
- package/package.json +8 -6
- package/types/teamsfx.d.ts +9 -3
package/dist/index.node.cjs.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var tslib = require('tslib');
|
|
6
5
|
var jwt_decode = require('jwt-decode');
|
|
6
|
+
var tslib = require('tslib');
|
|
7
7
|
var msalNode = require('@azure/msal-node');
|
|
8
8
|
var crypto = require('crypto');
|
|
9
9
|
var microsoftGraphClient = require('@microsoft/microsoft-graph-client');
|
|
@@ -17,6 +17,7 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
|
|
|
17
17
|
var jwt_decode__default = /*#__PURE__*/_interopDefaultLegacy(jwt_decode);
|
|
18
18
|
|
|
19
19
|
// Copyright (c) Microsoft Corporation.
|
|
20
|
+
// Licensed under the MIT license.
|
|
20
21
|
/**
|
|
21
22
|
* Error code to trace the error types.
|
|
22
23
|
* @beta
|
|
@@ -67,35 +68,35 @@ exports.ErrorCode = void 0;
|
|
|
67
68
|
* Operation failed.
|
|
68
69
|
*/
|
|
69
70
|
ErrorCode["FailedOperation"] = "FailedOperation";
|
|
71
|
+
/**
|
|
72
|
+
* Invalid response error.
|
|
73
|
+
*/
|
|
74
|
+
ErrorCode["InvalidResponse"] = "InvalidResponse";
|
|
70
75
|
})(exports.ErrorCode || (exports.ErrorCode = {}));
|
|
71
76
|
/**
|
|
72
77
|
* @internal
|
|
73
78
|
*/
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
ErrorMessage.OnlyMSTeamsChannelSupported = "{0} is only supported in MS Teams Channel";
|
|
90
|
-
return ErrorMessage;
|
|
91
|
-
}());
|
|
79
|
+
class ErrorMessage {
|
|
80
|
+
}
|
|
81
|
+
// InvalidConfiguration Error
|
|
82
|
+
ErrorMessage.InvalidConfiguration = "{0} in configuration is invalid: {1}.";
|
|
83
|
+
ErrorMessage.ConfigurationNotExists = "Configuration does not exist. {0}";
|
|
84
|
+
ErrorMessage.ResourceConfigurationNotExists = "{0} resource configuration does not exist.";
|
|
85
|
+
ErrorMessage.MissingResourceConfiguration = "Missing resource configuration with type: {0}, name: {1}.";
|
|
86
|
+
ErrorMessage.AuthenticationConfigurationNotExists = "Authentication configuration does not exist.";
|
|
87
|
+
// RuntimeNotSupported Error
|
|
88
|
+
ErrorMessage.BrowserRuntimeNotSupported = "{0} is not supported in browser.";
|
|
89
|
+
ErrorMessage.NodejsRuntimeNotSupported = "{0} is not supported in Node.";
|
|
90
|
+
// Internal Error
|
|
91
|
+
ErrorMessage.FailToAcquireTokenOnBehalfOfUser = "Failed to acquire access token on behalf of user: {0}";
|
|
92
|
+
// ChannelNotSupported Error
|
|
93
|
+
ErrorMessage.OnlyMSTeamsChannelSupported = "{0} is only supported in MS Teams Channel";
|
|
92
94
|
/**
|
|
93
95
|
* Error class with code and message thrown by the SDK.
|
|
94
96
|
*
|
|
95
97
|
* @beta
|
|
96
98
|
*/
|
|
97
|
-
|
|
98
|
-
tslib.__extends(ErrorWithCode, _super);
|
|
99
|
+
class ErrorWithCode extends Error {
|
|
99
100
|
/**
|
|
100
101
|
* Constructor of ErrorWithCode.
|
|
101
102
|
*
|
|
@@ -104,21 +105,17 @@ var ErrorWithCode = /** @class */ (function (_super) {
|
|
|
104
105
|
*
|
|
105
106
|
* @beta
|
|
106
107
|
*/
|
|
107
|
-
|
|
108
|
-
var _newTarget = this.constructor;
|
|
109
|
-
var _this = this;
|
|
108
|
+
constructor(message, code) {
|
|
110
109
|
if (!code) {
|
|
111
|
-
|
|
112
|
-
return
|
|
110
|
+
super(message);
|
|
111
|
+
return this;
|
|
113
112
|
}
|
|
114
|
-
|
|
115
|
-
Object.setPrototypeOf(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return _this;
|
|
113
|
+
super(message);
|
|
114
|
+
Object.setPrototypeOf(this, ErrorWithCode.prototype);
|
|
115
|
+
this.name = `${new.target.name}.${code}`;
|
|
116
|
+
this.code = code;
|
|
119
117
|
}
|
|
120
|
-
|
|
121
|
-
}(Error));
|
|
118
|
+
}
|
|
122
119
|
|
|
123
120
|
// Copyright (c) Microsoft Corporation.
|
|
124
121
|
// Licensed under the MIT license.
|
|
@@ -186,8 +183,8 @@ function setLogLevel(level) {
|
|
|
186
183
|
function getLogLevel() {
|
|
187
184
|
return internalLogger.level;
|
|
188
185
|
}
|
|
189
|
-
|
|
190
|
-
|
|
186
|
+
class InternalLogger {
|
|
187
|
+
constructor(name, logLevel) {
|
|
191
188
|
this.level = undefined;
|
|
192
189
|
this.defaultLogger = {
|
|
193
190
|
verbose: console.debug,
|
|
@@ -198,31 +195,31 @@ var InternalLogger = /** @class */ (function () {
|
|
|
198
195
|
this.name = name;
|
|
199
196
|
this.level = logLevel;
|
|
200
197
|
}
|
|
201
|
-
|
|
202
|
-
this.log(exports.LogLevel.Error,
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
this.log(exports.LogLevel.Warn,
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
this.log(exports.LogLevel.Info,
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
this.log(exports.LogLevel.Verbose,
|
|
212
|
-
}
|
|
213
|
-
|
|
198
|
+
error(message) {
|
|
199
|
+
this.log(exports.LogLevel.Error, (x) => x.error, message);
|
|
200
|
+
}
|
|
201
|
+
warn(message) {
|
|
202
|
+
this.log(exports.LogLevel.Warn, (x) => x.warn, message);
|
|
203
|
+
}
|
|
204
|
+
info(message) {
|
|
205
|
+
this.log(exports.LogLevel.Info, (x) => x.info, message);
|
|
206
|
+
}
|
|
207
|
+
verbose(message) {
|
|
208
|
+
this.log(exports.LogLevel.Verbose, (x) => x.verbose, message);
|
|
209
|
+
}
|
|
210
|
+
log(logLevel, logFunction, message) {
|
|
214
211
|
if (message.trim() === "") {
|
|
215
212
|
return;
|
|
216
213
|
}
|
|
217
|
-
|
|
218
|
-
|
|
214
|
+
const timestamp = new Date().toUTCString();
|
|
215
|
+
let logHeader;
|
|
219
216
|
if (this.name) {
|
|
220
|
-
logHeader =
|
|
217
|
+
logHeader = `[${timestamp}] : @microsoft/teamsfx - ${this.name} : ${exports.LogLevel[logLevel]} - `;
|
|
221
218
|
}
|
|
222
219
|
else {
|
|
223
|
-
logHeader =
|
|
220
|
+
logHeader = `[${timestamp}] : @microsoft/teamsfx : ${exports.LogLevel[logLevel]} - `;
|
|
224
221
|
}
|
|
225
|
-
|
|
222
|
+
const logMessage = `${logHeader}${message}`;
|
|
226
223
|
if (this.level !== undefined && this.level <= logLevel) {
|
|
227
224
|
if (this.customLogger) {
|
|
228
225
|
logFunction(this.customLogger)(logMessage);
|
|
@@ -234,15 +231,14 @@ var InternalLogger = /** @class */ (function () {
|
|
|
234
231
|
logFunction(this.defaultLogger)(logMessage);
|
|
235
232
|
}
|
|
236
233
|
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
}());
|
|
234
|
+
}
|
|
235
|
+
}
|
|
240
236
|
/**
|
|
241
237
|
* Logger instance used internally
|
|
242
238
|
*
|
|
243
239
|
* @internal
|
|
244
240
|
*/
|
|
245
|
-
|
|
241
|
+
const internalLogger = new InternalLogger();
|
|
246
242
|
/**
|
|
247
243
|
* Set custom logger. Use the output functions if it's set. Priority is higher than setLogFunction.
|
|
248
244
|
*
|
|
@@ -295,14 +291,14 @@ function setLogFunction(logFunction) {
|
|
|
295
291
|
*/
|
|
296
292
|
function parseJwt(token) {
|
|
297
293
|
try {
|
|
298
|
-
|
|
294
|
+
const tokenObj = jwt_decode__default["default"](token);
|
|
299
295
|
if (!tokenObj || !tokenObj.exp) {
|
|
300
296
|
throw new ErrorWithCode("Decoded token is null or exp claim does not exists.", exports.ErrorCode.InternalError);
|
|
301
297
|
}
|
|
302
298
|
return tokenObj;
|
|
303
299
|
}
|
|
304
300
|
catch (err) {
|
|
305
|
-
|
|
301
|
+
const errorMsg = "Parse jwt token failed in node env with error: " + err.message;
|
|
306
302
|
internalLogger.error(errorMsg);
|
|
307
303
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InternalError);
|
|
308
304
|
}
|
|
@@ -312,12 +308,12 @@ function parseJwt(token) {
|
|
|
312
308
|
*/
|
|
313
309
|
function getUserInfoFromSsoToken(ssoToken) {
|
|
314
310
|
if (!ssoToken) {
|
|
315
|
-
|
|
311
|
+
const errorMsg = "SSO token is undefined.";
|
|
316
312
|
internalLogger.error(errorMsg);
|
|
317
313
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidParameter);
|
|
318
314
|
}
|
|
319
|
-
|
|
320
|
-
|
|
315
|
+
const tokenObject = parseJwt(ssoToken);
|
|
316
|
+
const userInfo = {
|
|
321
317
|
displayName: tokenObject.name,
|
|
322
318
|
objectId: tokenObject.oid,
|
|
323
319
|
preferredUserName: "",
|
|
@@ -344,12 +340,8 @@ function getUserInfoFromSsoToken(ssoToken) {
|
|
|
344
340
|
*
|
|
345
341
|
* @internal
|
|
346
342
|
*/
|
|
347
|
-
function formatString(str) {
|
|
348
|
-
|
|
349
|
-
for (var _i = 1; _i < arguments.length; _i++) {
|
|
350
|
-
replacements[_i - 1] = arguments[_i];
|
|
351
|
-
}
|
|
352
|
-
var args = replacements;
|
|
343
|
+
function formatString(str, ...replacements) {
|
|
344
|
+
const args = replacements;
|
|
353
345
|
return str.replace(/{(\d+)}/g, function (match, number) {
|
|
354
346
|
return typeof args[number] != "undefined" ? args[number] : match;
|
|
355
347
|
});
|
|
@@ -367,10 +359,10 @@ function validateScopesType(value) {
|
|
|
367
359
|
return;
|
|
368
360
|
}
|
|
369
361
|
// string array
|
|
370
|
-
if (Array.isArray(value) && value.length > 0 && value.every(
|
|
362
|
+
if (Array.isArray(value) && value.length > 0 && value.every((item) => typeof item === "string")) {
|
|
371
363
|
return;
|
|
372
364
|
}
|
|
373
|
-
|
|
365
|
+
const errorMsg = "The type of scopes is not valid, it must be string or string array";
|
|
374
366
|
internalLogger.error(errorMsg);
|
|
375
367
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidParameter);
|
|
376
368
|
}
|
|
@@ -378,20 +370,20 @@ function validateScopesType(value) {
|
|
|
378
370
|
* @internal
|
|
379
371
|
*/
|
|
380
372
|
function getScopesArray(scopes) {
|
|
381
|
-
|
|
382
|
-
return scopesArray.filter(
|
|
373
|
+
const scopesArray = typeof scopes === "string" ? scopes.split(" ") : scopes;
|
|
374
|
+
return scopesArray.filter((x) => x !== null && x !== "");
|
|
383
375
|
}
|
|
384
376
|
/**
|
|
385
377
|
* @internal
|
|
386
378
|
*/
|
|
387
379
|
function getAuthority(authorityHost, tenantId) {
|
|
388
|
-
|
|
380
|
+
const normalizedAuthorityHost = authorityHost.replace(/\/+$/g, "");
|
|
389
381
|
return normalizedAuthorityHost + "/" + tenantId;
|
|
390
382
|
}
|
|
391
383
|
/**
|
|
392
384
|
* @internal
|
|
393
385
|
*/
|
|
394
|
-
|
|
386
|
+
const isNode = typeof process !== "undefined" &&
|
|
395
387
|
!!process.version &&
|
|
396
388
|
!!process.versions &&
|
|
397
389
|
!!process.versions.node;
|
|
@@ -401,7 +393,7 @@ var isNode = typeof process !== "undefined" &&
|
|
|
401
393
|
* Global configuration instance
|
|
402
394
|
*
|
|
403
395
|
*/
|
|
404
|
-
|
|
396
|
+
let config;
|
|
405
397
|
/**
|
|
406
398
|
* Initialize configuration from environment variables or configuration object and set the global instance
|
|
407
399
|
*
|
|
@@ -416,7 +408,7 @@ function loadConfiguration(configuration) {
|
|
|
416
408
|
// browser environment
|
|
417
409
|
if (!isNode) {
|
|
418
410
|
if (!configuration) {
|
|
419
|
-
|
|
411
|
+
const errorMsg = "You are running the code in browser. Configuration must be passed in.";
|
|
420
412
|
internalLogger.error(errorMsg);
|
|
421
413
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidParameter);
|
|
422
414
|
}
|
|
@@ -424,9 +416,9 @@ function loadConfiguration(configuration) {
|
|
|
424
416
|
return;
|
|
425
417
|
}
|
|
426
418
|
// node environment
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
419
|
+
let newAuthentication;
|
|
420
|
+
let newResources = [];
|
|
421
|
+
const defaultResourceName = "default";
|
|
430
422
|
if (configuration === null || configuration === void 0 ? void 0 : configuration.authentication) {
|
|
431
423
|
newAuthentication = configuration.authentication;
|
|
432
424
|
}
|
|
@@ -484,15 +476,14 @@ function loadConfiguration(configuration) {
|
|
|
484
476
|
*
|
|
485
477
|
* @beta
|
|
486
478
|
*/
|
|
487
|
-
function getResourceConfiguration(resourceType, resourceName) {
|
|
479
|
+
function getResourceConfiguration(resourceType, resourceName = "default") {
|
|
488
480
|
var _a;
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
var result = (_a = config.resources) === null || _a === void 0 ? void 0 : _a.find(function (item) { return item.type === resourceType && item.name === resourceName; });
|
|
481
|
+
internalLogger.info(`Get resource configuration of ${exports.ResourceType[resourceType]} from ${resourceName}`);
|
|
482
|
+
const result = (_a = config.resources) === null || _a === void 0 ? void 0 : _a.find((item) => item.type === resourceType && item.name === resourceName);
|
|
492
483
|
if (result) {
|
|
493
484
|
return result.properties;
|
|
494
485
|
}
|
|
495
|
-
|
|
486
|
+
const errorMsg = formatString(ErrorMessage.MissingResourceConfiguration, exports.ResourceType[resourceType], resourceName);
|
|
496
487
|
internalLogger.error(errorMsg);
|
|
497
488
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidConfiguration);
|
|
498
489
|
}
|
|
@@ -510,7 +501,7 @@ function getAuthenticationConfiguration() {
|
|
|
510
501
|
if (config) {
|
|
511
502
|
return config.authentication;
|
|
512
503
|
}
|
|
513
|
-
|
|
504
|
+
const errorMsg = "Please call loadConfiguration() first before calling getAuthenticationConfiguration().";
|
|
514
505
|
internalLogger.error(errorMsg);
|
|
515
506
|
throw new ErrorWithCode(formatString(ErrorMessage.ConfigurationNotExists, errorMsg), exports.ErrorCode.InvalidConfiguration);
|
|
516
507
|
}
|
|
@@ -519,9 +510,9 @@ function getAuthenticationConfiguration() {
|
|
|
519
510
|
* @internal
|
|
520
511
|
*/
|
|
521
512
|
function createConfidentialClientApplication(authentication) {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
513
|
+
const authority = getAuthority(authentication.authorityHost, authentication.tenantId);
|
|
514
|
+
const clientCertificate = parseCertificate(authentication.certificateContent);
|
|
515
|
+
const auth = {
|
|
525
516
|
clientId: authentication.clientId,
|
|
526
517
|
authority: authority,
|
|
527
518
|
};
|
|
@@ -532,7 +523,7 @@ function createConfidentialClientApplication(authentication) {
|
|
|
532
523
|
auth.clientSecret = authentication.clientSecret;
|
|
533
524
|
}
|
|
534
525
|
return new msalNode.ConfidentialClientApplication({
|
|
535
|
-
auth
|
|
526
|
+
auth,
|
|
536
527
|
});
|
|
537
528
|
}
|
|
538
529
|
/**
|
|
@@ -542,14 +533,14 @@ function parseCertificate(certificateContent) {
|
|
|
542
533
|
if (!certificateContent) {
|
|
543
534
|
return undefined;
|
|
544
535
|
}
|
|
545
|
-
|
|
546
|
-
|
|
536
|
+
const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/;
|
|
537
|
+
const match = certificatePattern.exec(certificateContent);
|
|
547
538
|
if (!match) {
|
|
548
|
-
|
|
539
|
+
const errorMsg = "The certificate content does not contain a PEM-encoded certificate.";
|
|
549
540
|
internalLogger.error(errorMsg);
|
|
550
541
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidCertificate);
|
|
551
542
|
}
|
|
552
|
-
|
|
543
|
+
const thumbprint = crypto.createHash("sha1")
|
|
553
544
|
.update(Buffer.from(match[3], "base64"))
|
|
554
545
|
.digest("hex")
|
|
555
546
|
.toUpperCase();
|
|
@@ -574,7 +565,7 @@ function parseCertificate(certificateContent) {
|
|
|
574
565
|
*
|
|
575
566
|
* @beta
|
|
576
567
|
*/
|
|
577
|
-
|
|
568
|
+
class M365TenantCredential {
|
|
578
569
|
/**
|
|
579
570
|
* Constructor of M365TenantCredential.
|
|
580
571
|
*
|
|
@@ -586,9 +577,9 @@ var M365TenantCredential = /** @class */ (function () {
|
|
|
586
577
|
*
|
|
587
578
|
* @beta
|
|
588
579
|
*/
|
|
589
|
-
|
|
580
|
+
constructor() {
|
|
590
581
|
internalLogger.info("Create M365 tenant credential");
|
|
591
|
-
|
|
582
|
+
const config = this.loadAndValidateConfig();
|
|
592
583
|
this.msalClient = createConfidentialClientApplication(config);
|
|
593
584
|
}
|
|
594
585
|
/**
|
|
@@ -617,54 +608,44 @@ var M365TenantCredential = /** @class */ (function () {
|
|
|
617
608
|
*
|
|
618
609
|
* @beta
|
|
619
610
|
*/
|
|
620
|
-
|
|
621
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
case 2:
|
|
637
|
-
authenticationResult = _a.sent();
|
|
638
|
-
if (authenticationResult) {
|
|
639
|
-
accessToken = {
|
|
640
|
-
token: authenticationResult.accessToken,
|
|
641
|
-
expiresOnTimestamp: authenticationResult.expiresOn.getTime(),
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
return [3 /*break*/, 4];
|
|
645
|
-
case 3:
|
|
646
|
-
err_1 = _a.sent();
|
|
647
|
-
errorMsg = "Get M365 tenant credential failed with error: " + err_1.message;
|
|
648
|
-
internalLogger.error(errorMsg);
|
|
649
|
-
throw new ErrorWithCode(errorMsg, exports.ErrorCode.ServiceError);
|
|
650
|
-
case 4:
|
|
651
|
-
if (!accessToken) {
|
|
652
|
-
errorMsg = "Get M365 tenant credential access token failed with empty access token";
|
|
653
|
-
internalLogger.error(errorMsg);
|
|
654
|
-
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InternalError);
|
|
655
|
-
}
|
|
656
|
-
return [2 /*return*/, accessToken];
|
|
611
|
+
getToken(scopes, options) {
|
|
612
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
613
|
+
let accessToken;
|
|
614
|
+
validateScopesType(scopes);
|
|
615
|
+
const scopesStr = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
616
|
+
internalLogger.info("Get access token with scopes: " + scopesStr);
|
|
617
|
+
try {
|
|
618
|
+
const scopesArray = getScopesArray(scopes);
|
|
619
|
+
const authenticationResult = yield this.msalClient.acquireTokenByClientCredential({
|
|
620
|
+
scopes: scopesArray,
|
|
621
|
+
});
|
|
622
|
+
if (authenticationResult) {
|
|
623
|
+
accessToken = {
|
|
624
|
+
token: authenticationResult.accessToken,
|
|
625
|
+
expiresOnTimestamp: authenticationResult.expiresOn.getTime(),
|
|
626
|
+
};
|
|
657
627
|
}
|
|
658
|
-
}
|
|
628
|
+
}
|
|
629
|
+
catch (err) {
|
|
630
|
+
const errorMsg = "Get M365 tenant credential failed with error: " + err.message;
|
|
631
|
+
internalLogger.error(errorMsg);
|
|
632
|
+
throw new ErrorWithCode(errorMsg, exports.ErrorCode.ServiceError);
|
|
633
|
+
}
|
|
634
|
+
if (!accessToken) {
|
|
635
|
+
const errorMsg = "Get M365 tenant credential access token failed with empty access token";
|
|
636
|
+
internalLogger.error(errorMsg);
|
|
637
|
+
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InternalError);
|
|
638
|
+
}
|
|
639
|
+
return accessToken;
|
|
659
640
|
});
|
|
660
|
-
}
|
|
641
|
+
}
|
|
661
642
|
/**
|
|
662
643
|
* Load and validate authentication configuration
|
|
663
644
|
* @returns Authentication configuration
|
|
664
645
|
*/
|
|
665
|
-
|
|
646
|
+
loadAndValidateConfig() {
|
|
666
647
|
internalLogger.verbose("Validate authentication configuration");
|
|
667
|
-
|
|
648
|
+
const config = getAuthenticationConfiguration();
|
|
668
649
|
if (!config) {
|
|
669
650
|
internalLogger.error(ErrorMessage.AuthenticationConfigurationNotExists);
|
|
670
651
|
throw new ErrorWithCode(ErrorMessage.AuthenticationConfigurationNotExists, exports.ErrorCode.InvalidConfiguration);
|
|
@@ -672,7 +653,7 @@ var M365TenantCredential = /** @class */ (function () {
|
|
|
672
653
|
if (config.clientId && (config.clientSecret || config.certificateContent) && config.tenantId) {
|
|
673
654
|
return config;
|
|
674
655
|
}
|
|
675
|
-
|
|
656
|
+
const missingValues = [];
|
|
676
657
|
if (!config.clientId) {
|
|
677
658
|
missingValues.push("clientId");
|
|
678
659
|
}
|
|
@@ -682,12 +663,11 @@ var M365TenantCredential = /** @class */ (function () {
|
|
|
682
663
|
if (!config.tenantId) {
|
|
683
664
|
missingValues.push("tenantId");
|
|
684
665
|
}
|
|
685
|
-
|
|
666
|
+
const errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingValues.join(", "), "undefined");
|
|
686
667
|
internalLogger.error(errorMsg);
|
|
687
668
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidConfiguration);
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
}());
|
|
669
|
+
}
|
|
670
|
+
}
|
|
691
671
|
|
|
692
672
|
// Copyright (c) Microsoft Corporation.
|
|
693
673
|
/**
|
|
@@ -704,7 +684,7 @@ var M365TenantCredential = /** @class */ (function () {
|
|
|
704
684
|
*
|
|
705
685
|
* @beta
|
|
706
686
|
*/
|
|
707
|
-
|
|
687
|
+
class OnBehalfOfUserCredential {
|
|
708
688
|
/**
|
|
709
689
|
* Constructor of OnBehalfOfUserCredential
|
|
710
690
|
*
|
|
@@ -719,10 +699,10 @@ var OnBehalfOfUserCredential = /** @class */ (function () {
|
|
|
719
699
|
*
|
|
720
700
|
* @beta
|
|
721
701
|
*/
|
|
722
|
-
|
|
702
|
+
constructor(ssoToken) {
|
|
723
703
|
var _a, _b, _c, _d, _e;
|
|
724
704
|
internalLogger.info("Get on behalf of user credential");
|
|
725
|
-
|
|
705
|
+
const missingConfigurations = [];
|
|
726
706
|
if (!((_a = config === null || config === void 0 ? void 0 : config.authentication) === null || _a === void 0 ? void 0 : _a.clientId)) {
|
|
727
707
|
missingConfigurations.push("clientId");
|
|
728
708
|
}
|
|
@@ -736,12 +716,12 @@ var OnBehalfOfUserCredential = /** @class */ (function () {
|
|
|
736
716
|
missingConfigurations.push("tenantId");
|
|
737
717
|
}
|
|
738
718
|
if (missingConfigurations.length != 0) {
|
|
739
|
-
|
|
719
|
+
const errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingConfigurations.join(", "), "undefined");
|
|
740
720
|
internalLogger.error(errorMsg);
|
|
741
721
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidConfiguration);
|
|
742
722
|
}
|
|
743
723
|
this.msalClient = createConfidentialClientApplication(config.authentication);
|
|
744
|
-
|
|
724
|
+
const decodedSsoToken = parseJwt(ssoToken);
|
|
745
725
|
this.ssoToken = {
|
|
746
726
|
token: ssoToken,
|
|
747
727
|
expiresOnTimestamp: decodedSsoToken.exp,
|
|
@@ -782,55 +762,45 @@ var OnBehalfOfUserCredential = /** @class */ (function () {
|
|
|
782
762
|
*
|
|
783
763
|
* @beta
|
|
784
764
|
*/
|
|
785
|
-
|
|
786
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
errorMsg = "Sso token has already expired.";
|
|
797
|
-
internalLogger.error(errorMsg);
|
|
798
|
-
throw new ErrorWithCode(errorMsg, exports.ErrorCode.TokenExpiredError);
|
|
799
|
-
}
|
|
800
|
-
result = this.ssoToken;
|
|
801
|
-
return [3 /*break*/, 6];
|
|
802
|
-
case 1:
|
|
803
|
-
internalLogger.info("Get access token with scopes: " + scopesArray.join(" "));
|
|
804
|
-
authenticationResult = void 0;
|
|
805
|
-
_a.label = 2;
|
|
806
|
-
case 2:
|
|
807
|
-
_a.trys.push([2, 4, , 5]);
|
|
808
|
-
return [4 /*yield*/, this.msalClient.acquireTokenOnBehalfOf({
|
|
809
|
-
oboAssertion: this.ssoToken.token,
|
|
810
|
-
scopes: scopesArray,
|
|
811
|
-
})];
|
|
812
|
-
case 3:
|
|
813
|
-
authenticationResult = _a.sent();
|
|
814
|
-
return [3 /*break*/, 5];
|
|
815
|
-
case 4:
|
|
816
|
-
error_1 = _a.sent();
|
|
817
|
-
throw this.generateAuthServerError(error_1);
|
|
818
|
-
case 5:
|
|
819
|
-
if (!authenticationResult) {
|
|
820
|
-
errorMsg = "Access token is null";
|
|
821
|
-
internalLogger.error(errorMsg);
|
|
822
|
-
throw new ErrorWithCode(formatString(ErrorMessage.FailToAcquireTokenOnBehalfOfUser, errorMsg), exports.ErrorCode.InternalError);
|
|
823
|
-
}
|
|
824
|
-
result = {
|
|
825
|
-
token: authenticationResult.accessToken,
|
|
826
|
-
expiresOnTimestamp: authenticationResult.expiresOn.getTime(),
|
|
827
|
-
};
|
|
828
|
-
_a.label = 6;
|
|
829
|
-
case 6: return [2 /*return*/, result];
|
|
765
|
+
getToken(scopes, options) {
|
|
766
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
767
|
+
validateScopesType(scopes);
|
|
768
|
+
const scopesArray = getScopesArray(scopes);
|
|
769
|
+
let result;
|
|
770
|
+
if (!scopesArray.length) {
|
|
771
|
+
internalLogger.info("Get SSO token.");
|
|
772
|
+
if (Math.floor(Date.now() / 1000) > this.ssoToken.expiresOnTimestamp) {
|
|
773
|
+
const errorMsg = "Sso token has already expired.";
|
|
774
|
+
internalLogger.error(errorMsg);
|
|
775
|
+
throw new ErrorWithCode(errorMsg, exports.ErrorCode.TokenExpiredError);
|
|
830
776
|
}
|
|
831
|
-
|
|
777
|
+
result = this.ssoToken;
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
|
+
internalLogger.info("Get access token with scopes: " + scopesArray.join(" "));
|
|
781
|
+
let authenticationResult;
|
|
782
|
+
try {
|
|
783
|
+
authenticationResult = yield this.msalClient.acquireTokenOnBehalfOf({
|
|
784
|
+
oboAssertion: this.ssoToken.token,
|
|
785
|
+
scopes: scopesArray,
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
catch (error) {
|
|
789
|
+
throw this.generateAuthServerError(error);
|
|
790
|
+
}
|
|
791
|
+
if (!authenticationResult) {
|
|
792
|
+
const errorMsg = "Access token is null";
|
|
793
|
+
internalLogger.error(errorMsg);
|
|
794
|
+
throw new ErrorWithCode(formatString(ErrorMessage.FailToAcquireTokenOnBehalfOfUser, errorMsg), exports.ErrorCode.InternalError);
|
|
795
|
+
}
|
|
796
|
+
result = {
|
|
797
|
+
token: authenticationResult.accessToken,
|
|
798
|
+
expiresOnTimestamp: authenticationResult.expiresOn.getTime(),
|
|
799
|
+
};
|
|
800
|
+
}
|
|
801
|
+
return result;
|
|
832
802
|
});
|
|
833
|
-
}
|
|
803
|
+
}
|
|
834
804
|
/**
|
|
835
805
|
* Get basic user info from SSO token.
|
|
836
806
|
*
|
|
@@ -846,30 +816,29 @@ var OnBehalfOfUserCredential = /** @class */ (function () {
|
|
|
846
816
|
*
|
|
847
817
|
* @beta
|
|
848
818
|
*/
|
|
849
|
-
|
|
819
|
+
getUserInfo() {
|
|
850
820
|
internalLogger.info("Get basic user info from SSO token");
|
|
851
821
|
return getUserInfoFromSsoToken(this.ssoToken.token);
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
|
|
822
|
+
}
|
|
823
|
+
generateAuthServerError(err) {
|
|
824
|
+
const errorMessage = err.errorMessage;
|
|
855
825
|
if (err.name === "InteractionRequiredAuthError") {
|
|
856
|
-
|
|
826
|
+
const fullErrorMsg = "Failed to get access token from AAD server, interaction required: " + errorMessage;
|
|
857
827
|
internalLogger.warn(fullErrorMsg);
|
|
858
828
|
return new ErrorWithCode(fullErrorMsg, exports.ErrorCode.UiRequiredError);
|
|
859
829
|
}
|
|
860
830
|
else if (errorMessage && errorMessage.indexOf("AADSTS500133") >= 0) {
|
|
861
|
-
|
|
831
|
+
const fullErrorMsg = "Failed to get access token from AAD server, sso token expired: " + errorMessage;
|
|
862
832
|
internalLogger.error(fullErrorMsg);
|
|
863
833
|
return new ErrorWithCode(fullErrorMsg, exports.ErrorCode.TokenExpiredError);
|
|
864
834
|
}
|
|
865
835
|
else {
|
|
866
|
-
|
|
836
|
+
const fullErrorMsg = formatString(ErrorMessage.FailToAcquireTokenOnBehalfOfUser, errorMessage);
|
|
867
837
|
internalLogger.error(fullErrorMsg);
|
|
868
838
|
return new ErrorWithCode(fullErrorMsg, exports.ErrorCode.ServiceError);
|
|
869
839
|
}
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
}());
|
|
840
|
+
}
|
|
841
|
+
}
|
|
873
842
|
|
|
874
843
|
// Copyright (c) Microsoft Corporation.
|
|
875
844
|
/**
|
|
@@ -880,14 +849,14 @@ var OnBehalfOfUserCredential = /** @class */ (function () {
|
|
|
880
849
|
*
|
|
881
850
|
* @beta
|
|
882
851
|
*/
|
|
883
|
-
|
|
852
|
+
class TeamsUserCredential {
|
|
884
853
|
/**
|
|
885
854
|
* Constructor of TeamsUserCredential.
|
|
886
855
|
* @remarks
|
|
887
856
|
* Can only be used within Teams.
|
|
888
857
|
* @beta
|
|
889
858
|
*/
|
|
890
|
-
|
|
859
|
+
constructor() {
|
|
891
860
|
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
|
|
892
861
|
}
|
|
893
862
|
/**
|
|
@@ -896,46 +865,41 @@ var TeamsUserCredential = /** @class */ (function () {
|
|
|
896
865
|
* Can only be used within Teams.
|
|
897
866
|
* @beta
|
|
898
867
|
*/
|
|
899
|
-
|
|
900
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
901
|
-
|
|
902
|
-
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
|
|
903
|
-
});
|
|
868
|
+
login(scopes) {
|
|
869
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
870
|
+
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
|
|
904
871
|
});
|
|
905
|
-
}
|
|
872
|
+
}
|
|
906
873
|
/**
|
|
907
874
|
* Get access token from credential.
|
|
908
875
|
* @remarks
|
|
909
876
|
* Can only be used within Teams.
|
|
910
877
|
* @beta
|
|
911
878
|
*/
|
|
912
|
-
|
|
913
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
914
|
-
|
|
915
|
-
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
|
|
916
|
-
});
|
|
879
|
+
getToken(scopes, options) {
|
|
880
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
881
|
+
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
|
|
917
882
|
});
|
|
918
|
-
}
|
|
883
|
+
}
|
|
919
884
|
/**
|
|
920
885
|
* Get basic user info from SSO token
|
|
921
886
|
* @remarks
|
|
922
887
|
* Can only be used within Teams.
|
|
923
888
|
* @beta
|
|
924
889
|
*/
|
|
925
|
-
|
|
890
|
+
getUserInfo() {
|
|
926
891
|
throw new ErrorWithCode(formatString(ErrorMessage.NodejsRuntimeNotSupported, "TeamsUserCredential"), exports.ErrorCode.RuntimeNotSupported);
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
}());
|
|
892
|
+
}
|
|
893
|
+
}
|
|
930
894
|
|
|
931
895
|
// Copyright (c) Microsoft Corporation.
|
|
932
|
-
|
|
896
|
+
const defaultScope = "https://graph.microsoft.com/.default";
|
|
933
897
|
/**
|
|
934
898
|
* Microsoft Graph auth provider for Teams Framework
|
|
935
899
|
*
|
|
936
900
|
* @beta
|
|
937
901
|
*/
|
|
938
|
-
|
|
902
|
+
class MsGraphAuthProvider {
|
|
939
903
|
/**
|
|
940
904
|
* Constructor of MsGraphAuthProvider.
|
|
941
905
|
*
|
|
@@ -948,9 +912,9 @@ var MsGraphAuthProvider = /** @class */ (function () {
|
|
|
948
912
|
*
|
|
949
913
|
* @beta
|
|
950
914
|
*/
|
|
951
|
-
|
|
915
|
+
constructor(credential, scopes) {
|
|
952
916
|
this.credential = credential;
|
|
953
|
-
|
|
917
|
+
let scopesStr = defaultScope;
|
|
954
918
|
if (scopes) {
|
|
955
919
|
validateScopesType(scopes);
|
|
956
920
|
scopesStr = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
@@ -958,7 +922,7 @@ var MsGraphAuthProvider = /** @class */ (function () {
|
|
|
958
922
|
scopesStr = defaultScope;
|
|
959
923
|
}
|
|
960
924
|
}
|
|
961
|
-
internalLogger.info(
|
|
925
|
+
internalLogger.info(`Create Microsoft Graph Authentication Provider with scopes: '${scopesStr}'`);
|
|
962
926
|
this.scopes = scopesStr;
|
|
963
927
|
}
|
|
964
928
|
/**
|
|
@@ -973,32 +937,23 @@ var MsGraphAuthProvider = /** @class */ (function () {
|
|
|
973
937
|
* @returns Access token from the credential.
|
|
974
938
|
*
|
|
975
939
|
*/
|
|
976
|
-
|
|
977
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
resolve(accessToken.token);
|
|
989
|
-
}
|
|
990
|
-
else {
|
|
991
|
-
var errorMsg = "Graph access token is undefined or empty";
|
|
992
|
-
internalLogger.error(errorMsg);
|
|
993
|
-
reject(new ErrorWithCode(errorMsg, exports.ErrorCode.InternalError));
|
|
994
|
-
}
|
|
995
|
-
})];
|
|
940
|
+
getAccessToken() {
|
|
941
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
942
|
+
internalLogger.info(`Get Graph Access token with scopes: '${this.scopes}'`);
|
|
943
|
+
const accessToken = yield this.credential.getToken(this.scopes);
|
|
944
|
+
return new Promise((resolve, reject) => {
|
|
945
|
+
if (accessToken) {
|
|
946
|
+
resolve(accessToken.token);
|
|
947
|
+
}
|
|
948
|
+
else {
|
|
949
|
+
const errorMsg = "Graph access token is undefined or empty";
|
|
950
|
+
internalLogger.error(errorMsg);
|
|
951
|
+
reject(new ErrorWithCode(errorMsg, exports.ErrorCode.InternalError));
|
|
996
952
|
}
|
|
997
953
|
});
|
|
998
954
|
});
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
}());
|
|
955
|
+
}
|
|
956
|
+
}
|
|
1002
957
|
|
|
1003
958
|
// Copyright (c) Microsoft Corporation.
|
|
1004
959
|
/**
|
|
@@ -1054,9 +1009,9 @@ var MsGraphAuthProvider = /** @class */ (function () {
|
|
|
1054
1009
|
*/
|
|
1055
1010
|
function createMicrosoftGraphClient(credential, scopes) {
|
|
1056
1011
|
internalLogger.info("Create Microsoft Graph Client");
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
authProvider
|
|
1012
|
+
const authProvider = new MsGraphAuthProvider(credential, scopes);
|
|
1013
|
+
const graphClient = microsoftGraphClient.Client.initWithMiddleware({
|
|
1014
|
+
authProvider,
|
|
1060
1015
|
});
|
|
1061
1016
|
return graphClient;
|
|
1062
1017
|
}
|
|
@@ -1070,8 +1025,8 @@ function createMicrosoftGraphClient(credential, scopes) {
|
|
|
1070
1025
|
* @beta
|
|
1071
1026
|
*
|
|
1072
1027
|
*/
|
|
1073
|
-
|
|
1074
|
-
|
|
1028
|
+
class DefaultTediousConnectionConfiguration {
|
|
1029
|
+
constructor() {
|
|
1075
1030
|
/**
|
|
1076
1031
|
* MSSQL default scope
|
|
1077
1032
|
* https://docs.microsoft.com/en-us/azure/app-service/app-service-web-tutorial-connect-msi
|
|
@@ -1081,6 +1036,8 @@ var DefaultTediousConnectionConfiguration = /** @class */ (function () {
|
|
|
1081
1036
|
/**
|
|
1082
1037
|
* Generate connection configuration consumed by tedious.
|
|
1083
1038
|
*
|
|
1039
|
+
* @param { string? } databaseName - specify database name to override default one if there are multiple databases.
|
|
1040
|
+
*
|
|
1084
1041
|
* @returns Connection configuration of tedious for the SQL.
|
|
1085
1042
|
*
|
|
1086
1043
|
* @throws {@link ErrorCode|InvalidConfiguration} when SQL config resource configuration is invalid.
|
|
@@ -1089,62 +1046,52 @@ var DefaultTediousConnectionConfiguration = /** @class */ (function () {
|
|
|
1089
1046
|
*
|
|
1090
1047
|
* @beta
|
|
1091
1048
|
*/
|
|
1092
|
-
|
|
1093
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
case 2:
|
|
1121
|
-
configWithToken = _a.sent();
|
|
1122
|
-
internalLogger.verbose("SQL configuration with MSI token generated");
|
|
1123
|
-
return [2 /*return*/, configWithToken];
|
|
1124
|
-
case 3:
|
|
1125
|
-
error_1 = _a.sent();
|
|
1126
|
-
throw error_1;
|
|
1127
|
-
case 4: return [2 /*return*/];
|
|
1128
|
-
}
|
|
1129
|
-
});
|
|
1049
|
+
getConfig(databaseName) {
|
|
1050
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1051
|
+
internalLogger.info("Get SQL configuration");
|
|
1052
|
+
const configuration = getResourceConfiguration(exports.ResourceType.SQL);
|
|
1053
|
+
if (!configuration) {
|
|
1054
|
+
const errMsg = "SQL resource configuration not exist";
|
|
1055
|
+
internalLogger.error(errMsg);
|
|
1056
|
+
throw new ErrorWithCode(errMsg, exports.ErrorCode.InvalidConfiguration);
|
|
1057
|
+
}
|
|
1058
|
+
try {
|
|
1059
|
+
this.isSQLConfigurationValid(configuration);
|
|
1060
|
+
}
|
|
1061
|
+
catch (err) {
|
|
1062
|
+
throw err;
|
|
1063
|
+
}
|
|
1064
|
+
if (!this.isMsiAuthentication()) {
|
|
1065
|
+
const configWithUPS = this.generateDefaultConfig(configuration, databaseName);
|
|
1066
|
+
internalLogger.verbose("SQL configuration with username and password generated");
|
|
1067
|
+
return configWithUPS;
|
|
1068
|
+
}
|
|
1069
|
+
try {
|
|
1070
|
+
const configWithToken = yield this.generateTokenConfig(configuration, databaseName);
|
|
1071
|
+
internalLogger.verbose("SQL configuration with MSI token generated");
|
|
1072
|
+
return configWithToken;
|
|
1073
|
+
}
|
|
1074
|
+
catch (error) {
|
|
1075
|
+
throw error;
|
|
1076
|
+
}
|
|
1130
1077
|
});
|
|
1131
|
-
}
|
|
1078
|
+
}
|
|
1132
1079
|
/**
|
|
1133
1080
|
* Check SQL use MSI identity or username and password.
|
|
1134
1081
|
*
|
|
1135
1082
|
* @returns false - login with SQL MSI identity, true - login with username and password.
|
|
1136
1083
|
* @internal
|
|
1137
1084
|
*/
|
|
1138
|
-
|
|
1085
|
+
isMsiAuthentication() {
|
|
1139
1086
|
internalLogger.verbose("Check connection config using MSI access token or username and password");
|
|
1140
|
-
|
|
1087
|
+
const configuration = getResourceConfiguration(exports.ResourceType.SQL);
|
|
1141
1088
|
if ((configuration === null || configuration === void 0 ? void 0 : configuration.sqlUsername) != null && (configuration === null || configuration === void 0 ? void 0 : configuration.sqlPassword) != null) {
|
|
1142
1089
|
internalLogger.verbose("Login with username and password");
|
|
1143
1090
|
return false;
|
|
1144
1091
|
}
|
|
1145
1092
|
internalLogger.verbose("Login with MSI identity");
|
|
1146
1093
|
return true;
|
|
1147
|
-
}
|
|
1094
|
+
}
|
|
1148
1095
|
/**
|
|
1149
1096
|
* check configuration is an available configurations.
|
|
1150
1097
|
* @param { SqlConfiguration } sqlConfig
|
|
@@ -1153,19 +1100,19 @@ var DefaultTediousConnectionConfiguration = /** @class */ (function () {
|
|
|
1153
1100
|
* false - configuration is not valid.
|
|
1154
1101
|
* @internal
|
|
1155
1102
|
*/
|
|
1156
|
-
|
|
1103
|
+
isSQLConfigurationValid(sqlConfig) {
|
|
1157
1104
|
internalLogger.verbose("Check SQL configuration if valid");
|
|
1158
1105
|
if (!sqlConfig.sqlServerEndpoint) {
|
|
1159
1106
|
internalLogger.error("SQL configuration is not valid without SQL server endpoint exist");
|
|
1160
1107
|
throw new ErrorWithCode("SQL configuration error without SQL server endpoint exist", exports.ErrorCode.InvalidConfiguration);
|
|
1161
1108
|
}
|
|
1162
1109
|
if (!(sqlConfig.sqlUsername && sqlConfig.sqlPassword) && !sqlConfig.sqlIdentityId) {
|
|
1163
|
-
|
|
1110
|
+
const errMsg = `SQL configuration is not valid without ${sqlConfig.sqlIdentityId ? "" : "identity id "} ${sqlConfig.sqlUsername ? "" : "SQL username "} ${sqlConfig.sqlPassword ? "" : "SQL password"} exist`;
|
|
1164
1111
|
internalLogger.error(errMsg);
|
|
1165
1112
|
throw new ErrorWithCode(errMsg, exports.ErrorCode.InvalidConfiguration);
|
|
1166
1113
|
}
|
|
1167
1114
|
internalLogger.verbose("SQL configuration is valid");
|
|
1168
|
-
}
|
|
1115
|
+
}
|
|
1169
1116
|
/**
|
|
1170
1117
|
* Generate tedious connection configuration with default authentication type.
|
|
1171
1118
|
*
|
|
@@ -1174,9 +1121,13 @@ var DefaultTediousConnectionConfiguration = /** @class */ (function () {
|
|
|
1174
1121
|
* @returns Tedious connection configuration with username and password.
|
|
1175
1122
|
* @internal
|
|
1176
1123
|
*/
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1124
|
+
generateDefaultConfig(sqlConfig, databaseName) {
|
|
1125
|
+
if (databaseName === "") {
|
|
1126
|
+
internalLogger.warn(`SQL database name is empty string`);
|
|
1127
|
+
}
|
|
1128
|
+
const dbName = databaseName !== null && databaseName !== void 0 ? databaseName : sqlConfig.sqlDatabaseName;
|
|
1129
|
+
internalLogger.verbose(`SQL server ${sqlConfig.sqlServerEndpoint}, user name ${sqlConfig.sqlUsername}, database name ${dbName}`);
|
|
1130
|
+
const config = {
|
|
1180
1131
|
server: sqlConfig.sqlServerEndpoint,
|
|
1181
1132
|
authentication: {
|
|
1182
1133
|
type: TediousAuthenticationType.default,
|
|
@@ -1186,12 +1137,12 @@ var DefaultTediousConnectionConfiguration = /** @class */ (function () {
|
|
|
1186
1137
|
},
|
|
1187
1138
|
},
|
|
1188
1139
|
options: {
|
|
1189
|
-
database:
|
|
1140
|
+
database: dbName,
|
|
1190
1141
|
encrypt: true,
|
|
1191
1142
|
},
|
|
1192
1143
|
};
|
|
1193
1144
|
return config;
|
|
1194
|
-
}
|
|
1145
|
+
}
|
|
1195
1146
|
/**
|
|
1196
1147
|
* Generate tedious connection configuration with azure-active-directory-access-token authentication type.
|
|
1197
1148
|
*
|
|
@@ -1200,52 +1151,44 @@ var DefaultTediousConnectionConfiguration = /** @class */ (function () {
|
|
|
1200
1151
|
* @returns Tedious connection configuration with access token.
|
|
1201
1152
|
* @internal
|
|
1202
1153
|
*/
|
|
1203
|
-
|
|
1204
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
internalLogger.verbose("Generate token configuration success, server endpoint is " + sqlConfig.sqlServerEndpoint + ", database name is " + sqlConfig.sqlDatabaseName);
|
|
1239
|
-
return [2 /*return*/, config];
|
|
1240
|
-
}
|
|
1241
|
-
internalLogger.error("Generate token configuration, server endpoint is " + sqlConfig.sqlServerEndpoint + ", MSI token is not valid");
|
|
1242
|
-
throw new ErrorWithCode("MSI token is not valid", exports.ErrorCode.InternalError);
|
|
1243
|
-
}
|
|
1244
|
-
});
|
|
1154
|
+
generateTokenConfig(sqlConfig, databaseName) {
|
|
1155
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1156
|
+
internalLogger.verbose("Generate tedious config with MSI token");
|
|
1157
|
+
if (databaseName === "") {
|
|
1158
|
+
internalLogger.warn(`SQL database name is empty string`);
|
|
1159
|
+
}
|
|
1160
|
+
let token;
|
|
1161
|
+
try {
|
|
1162
|
+
const credential = new identity.ManagedIdentityCredential(sqlConfig.sqlIdentityId);
|
|
1163
|
+
token = yield credential.getToken(this.defaultSQLScope);
|
|
1164
|
+
}
|
|
1165
|
+
catch (error) {
|
|
1166
|
+
const errMsg = "Get user MSI token failed";
|
|
1167
|
+
internalLogger.error(errMsg);
|
|
1168
|
+
throw new ErrorWithCode(errMsg, exports.ErrorCode.InternalError);
|
|
1169
|
+
}
|
|
1170
|
+
if (token) {
|
|
1171
|
+
const config = {
|
|
1172
|
+
server: sqlConfig.sqlServerEndpoint,
|
|
1173
|
+
authentication: {
|
|
1174
|
+
type: TediousAuthenticationType.MSI,
|
|
1175
|
+
options: {
|
|
1176
|
+
token: token.token,
|
|
1177
|
+
},
|
|
1178
|
+
},
|
|
1179
|
+
options: {
|
|
1180
|
+
database: databaseName !== null && databaseName !== void 0 ? databaseName : sqlConfig.sqlDatabaseName,
|
|
1181
|
+
encrypt: true,
|
|
1182
|
+
},
|
|
1183
|
+
};
|
|
1184
|
+
internalLogger.verbose(`Generate token configuration success, server endpoint is ${sqlConfig.sqlServerEndpoint}, database name is ${databaseName !== null && databaseName !== void 0 ? databaseName : sqlConfig.sqlDatabaseName}`);
|
|
1185
|
+
return config;
|
|
1186
|
+
}
|
|
1187
|
+
internalLogger.error(`Generate token configuration, server endpoint is ${sqlConfig.sqlServerEndpoint}, MSI token is not valid`);
|
|
1188
|
+
throw new ErrorWithCode("MSI token is not valid", exports.ErrorCode.InternalError);
|
|
1245
1189
|
});
|
|
1246
|
-
}
|
|
1247
|
-
|
|
1248
|
-
}());
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1249
1192
|
/**
|
|
1250
1193
|
* tedious connection config authentication type.
|
|
1251
1194
|
* https://tediousjs.github.io/tedious/api-connection.html
|
|
@@ -1258,19 +1201,18 @@ var TediousAuthenticationType;
|
|
|
1258
1201
|
})(TediousAuthenticationType || (TediousAuthenticationType = {}));
|
|
1259
1202
|
|
|
1260
1203
|
// Copyright (c) Microsoft Corporation.
|
|
1261
|
-
|
|
1204
|
+
const invokeResponseType = "invokeResponse";
|
|
1262
1205
|
/**
|
|
1263
1206
|
* Response body returned for a token exchange invoke activity.
|
|
1264
1207
|
*
|
|
1265
1208
|
* @beta
|
|
1266
1209
|
*/
|
|
1267
|
-
|
|
1268
|
-
|
|
1210
|
+
class TokenExchangeInvokeResponse {
|
|
1211
|
+
constructor(id, failureDetail) {
|
|
1269
1212
|
this.id = id;
|
|
1270
1213
|
this.failureDetail = failureDetail;
|
|
1271
1214
|
}
|
|
1272
|
-
|
|
1273
|
-
}());
|
|
1215
|
+
}
|
|
1274
1216
|
/**
|
|
1275
1217
|
* Creates a new prompt that leverage Teams Single Sign On (SSO) support for bot to automatically sign in user and
|
|
1276
1218
|
* help receive oauth token, asks the user to consent if needed.
|
|
@@ -1322,8 +1264,7 @@ var TokenExchangeInvokeResponse = /** @class */ (function () {
|
|
|
1322
1264
|
*
|
|
1323
1265
|
* @beta
|
|
1324
1266
|
*/
|
|
1325
|
-
|
|
1326
|
-
tslib.__extends(TeamsBotSsoPrompt, _super);
|
|
1267
|
+
class TeamsBotSsoPrompt extends botbuilderDialogs.Dialog {
|
|
1327
1268
|
/**
|
|
1328
1269
|
* Constructor of TeamsBotSsoPrompt.
|
|
1329
1270
|
*
|
|
@@ -1335,12 +1276,11 @@ var TeamsBotSsoPrompt = /** @class */ (function (_super) {
|
|
|
1335
1276
|
*
|
|
1336
1277
|
* @beta
|
|
1337
1278
|
*/
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1279
|
+
constructor(dialogId, settings) {
|
|
1280
|
+
super(dialogId);
|
|
1281
|
+
this.settings = settings;
|
|
1341
1282
|
validateScopesType(settings.scopes);
|
|
1342
1283
|
internalLogger.info("Create a new Teams Bot SSO Prompt");
|
|
1343
|
-
return _this;
|
|
1344
1284
|
}
|
|
1345
1285
|
/**
|
|
1346
1286
|
* Called when a prompt dialog is pushed onto the dialog stack and is being activated.
|
|
@@ -1358,47 +1298,39 @@ var TeamsBotSsoPrompt = /** @class */ (function (_super) {
|
|
|
1358
1298
|
*
|
|
1359
1299
|
* @beta
|
|
1360
1300
|
*/
|
|
1361
|
-
|
|
1301
|
+
beginDialog(dc) {
|
|
1362
1302
|
var _a;
|
|
1363
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
errorMsg = "type of timeout property in teamsBotSsoPromptSettings should be number.";
|
|
1375
|
-
internalLogger.error(errorMsg);
|
|
1376
|
-
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidParameter);
|
|
1377
|
-
}
|
|
1378
|
-
if (this.settings.timeout <= 0) {
|
|
1379
|
-
errorMsg = "value of timeout property in teamsBotSsoPromptSettings should be positive.";
|
|
1380
|
-
internalLogger.error(errorMsg);
|
|
1381
|
-
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidParameter);
|
|
1382
|
-
}
|
|
1383
|
-
timeout = this.settings.timeout;
|
|
1384
|
-
}
|
|
1385
|
-
if (this.settings.endOnInvalidMessage === undefined) {
|
|
1386
|
-
this.settings.endOnInvalidMessage = true;
|
|
1387
|
-
}
|
|
1388
|
-
state = (_a = dc.activeDialog) === null || _a === void 0 ? void 0 : _a.state;
|
|
1389
|
-
state.state = {};
|
|
1390
|
-
state.options = {};
|
|
1391
|
-
state.expires = new Date().getTime() + timeout;
|
|
1392
|
-
// Send OAuth card to get SSO token
|
|
1393
|
-
return [4 /*yield*/, this.sendOAuthCardAsync(dc.context)];
|
|
1394
|
-
case 1:
|
|
1395
|
-
// Send OAuth card to get SSO token
|
|
1396
|
-
_b.sent();
|
|
1397
|
-
return [2 /*return*/, botbuilderDialogs.Dialog.EndOfTurn];
|
|
1303
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1304
|
+
internalLogger.info("Begin Teams Bot SSO Prompt");
|
|
1305
|
+
this.ensureMsTeamsChannel(dc);
|
|
1306
|
+
// Initialize prompt state
|
|
1307
|
+
const default_timeout = 900000;
|
|
1308
|
+
let timeout = default_timeout;
|
|
1309
|
+
if (this.settings.timeout) {
|
|
1310
|
+
if (typeof this.settings.timeout != "number") {
|
|
1311
|
+
const errorMsg = "type of timeout property in teamsBotSsoPromptSettings should be number.";
|
|
1312
|
+
internalLogger.error(errorMsg);
|
|
1313
|
+
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidParameter);
|
|
1398
1314
|
}
|
|
1399
|
-
|
|
1315
|
+
if (this.settings.timeout <= 0) {
|
|
1316
|
+
const errorMsg = "value of timeout property in teamsBotSsoPromptSettings should be positive.";
|
|
1317
|
+
internalLogger.error(errorMsg);
|
|
1318
|
+
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidParameter);
|
|
1319
|
+
}
|
|
1320
|
+
timeout = this.settings.timeout;
|
|
1321
|
+
}
|
|
1322
|
+
if (this.settings.endOnInvalidMessage === undefined) {
|
|
1323
|
+
this.settings.endOnInvalidMessage = true;
|
|
1324
|
+
}
|
|
1325
|
+
const state = (_a = dc.activeDialog) === null || _a === void 0 ? void 0 : _a.state;
|
|
1326
|
+
state.state = {};
|
|
1327
|
+
state.options = {};
|
|
1328
|
+
state.expires = new Date().getTime() + timeout;
|
|
1329
|
+
// Send OAuth card to get SSO token
|
|
1330
|
+
yield this.sendOAuthCardAsync(dc.context);
|
|
1331
|
+
return botbuilderDialogs.Dialog.EndOfTurn;
|
|
1400
1332
|
});
|
|
1401
|
-
}
|
|
1333
|
+
}
|
|
1402
1334
|
/**
|
|
1403
1335
|
* Called when a prompt dialog is the active dialog and the user replied with a new activity.
|
|
1404
1336
|
*
|
|
@@ -1417,90 +1349,74 @@ var TeamsBotSsoPrompt = /** @class */ (function (_super) {
|
|
|
1417
1349
|
*
|
|
1418
1350
|
* @beta
|
|
1419
1351
|
*/
|
|
1420
|
-
|
|
1352
|
+
continueDialog(dc) {
|
|
1421
1353
|
var _a;
|
|
1422
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
return [4 /*yield*/, dc.endDialog(recognized.value)];
|
|
1447
|
-
case 4: return [2 /*return*/, _b.sent()];
|
|
1448
|
-
case 5: return [3 /*break*/, 8];
|
|
1449
|
-
case 6:
|
|
1450
|
-
if (!(isMessage && this.settings.endOnInvalidMessage)) return [3 /*break*/, 8];
|
|
1451
|
-
internalLogger.warn("End Teams Bot SSO Prompt due to invalid message");
|
|
1452
|
-
return [4 /*yield*/, dc.endDialog(undefined)];
|
|
1453
|
-
case 7: return [2 /*return*/, _b.sent()];
|
|
1454
|
-
case 8: return [2 /*return*/, botbuilderDialogs.Dialog.EndOfTurn];
|
|
1354
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1355
|
+
internalLogger.info("Continue Teams Bot SSO Prompt");
|
|
1356
|
+
this.ensureMsTeamsChannel(dc);
|
|
1357
|
+
// Check for timeout
|
|
1358
|
+
const state = (_a = dc.activeDialog) === null || _a === void 0 ? void 0 : _a.state;
|
|
1359
|
+
const isMessage = dc.context.activity.type === botbuilder.ActivityTypes.Message;
|
|
1360
|
+
const isTimeoutActivityType = isMessage ||
|
|
1361
|
+
this.isTeamsVerificationInvoke(dc.context) ||
|
|
1362
|
+
this.isTokenExchangeRequestInvoke(dc.context);
|
|
1363
|
+
// If the incoming Activity is a message, or an Activity Type normally handled by TeamsBotSsoPrompt,
|
|
1364
|
+
// check to see if this TeamsBotSsoPrompt Expiration has elapsed, and end the dialog if so.
|
|
1365
|
+
const hasTimedOut = isTimeoutActivityType && new Date().getTime() > state.expires;
|
|
1366
|
+
if (hasTimedOut) {
|
|
1367
|
+
internalLogger.warn("End Teams Bot SSO Prompt due to timeout");
|
|
1368
|
+
return yield dc.endDialog(undefined);
|
|
1369
|
+
}
|
|
1370
|
+
else {
|
|
1371
|
+
if (this.isTeamsVerificationInvoke(dc.context) ||
|
|
1372
|
+
this.isTokenExchangeRequestInvoke(dc.context)) {
|
|
1373
|
+
// Recognize token
|
|
1374
|
+
const recognized = yield this.recognizeToken(dc);
|
|
1375
|
+
if (recognized.succeeded) {
|
|
1376
|
+
return yield dc.endDialog(recognized.value);
|
|
1377
|
+
}
|
|
1455
1378
|
}
|
|
1456
|
-
|
|
1379
|
+
else if (isMessage && this.settings.endOnInvalidMessage) {
|
|
1380
|
+
internalLogger.warn("End Teams Bot SSO Prompt due to invalid message");
|
|
1381
|
+
return yield dc.endDialog(undefined);
|
|
1382
|
+
}
|
|
1383
|
+
return botbuilderDialogs.Dialog.EndOfTurn;
|
|
1384
|
+
}
|
|
1457
1385
|
});
|
|
1458
|
-
}
|
|
1386
|
+
}
|
|
1459
1387
|
/**
|
|
1460
1388
|
* Ensure bot is running in MS Teams since TeamsBotSsoPrompt is only supported in MS Teams channel.
|
|
1461
1389
|
* @param dc dialog context
|
|
1462
1390
|
* @throws {@link ErrorCode|ChannelNotSupported} if bot channel is not MS Teams
|
|
1463
1391
|
* @internal
|
|
1464
1392
|
*/
|
|
1465
|
-
|
|
1393
|
+
ensureMsTeamsChannel(dc) {
|
|
1466
1394
|
if (dc.context.activity.channelId != botbuilder.Channels.Msteams) {
|
|
1467
|
-
|
|
1395
|
+
const errorMsg = formatString(ErrorMessage.OnlyMSTeamsChannelSupported, "Teams Bot SSO Prompt");
|
|
1468
1396
|
internalLogger.error(errorMsg);
|
|
1469
1397
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.ChannelNotSupported);
|
|
1470
1398
|
}
|
|
1471
|
-
}
|
|
1399
|
+
}
|
|
1472
1400
|
/**
|
|
1473
1401
|
* Send OAuthCard that tells Teams to obtain an authentication token for the bot application.
|
|
1474
1402
|
* For details see https://docs.microsoft.com/en-us/microsoftteams/platform/bots/how-to/authentication/auth-aad-sso-bots.
|
|
1475
1403
|
*
|
|
1476
1404
|
* @internal
|
|
1477
1405
|
*/
|
|
1478
|
-
|
|
1479
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
signInResource = this.getSignInResource(loginHint);
|
|
1491
|
-
card = botbuilder.CardFactory.oauthCard("", "Teams SSO Sign In", "Sign In", signInResource.signInLink, signInResource.tokenExchangeResource);
|
|
1492
|
-
card.content.buttons[0].type = botbuilder.ActionTypes.Signin;
|
|
1493
|
-
msg = botbuilder.MessageFactory.attachment(card);
|
|
1494
|
-
// Send prompt
|
|
1495
|
-
return [4 /*yield*/, context.sendActivity(msg)];
|
|
1496
|
-
case 2:
|
|
1497
|
-
// Send prompt
|
|
1498
|
-
_a.sent();
|
|
1499
|
-
return [2 /*return*/];
|
|
1500
|
-
}
|
|
1501
|
-
});
|
|
1406
|
+
sendOAuthCardAsync(context) {
|
|
1407
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1408
|
+
internalLogger.verbose("Send OAuth card to get SSO token");
|
|
1409
|
+
const account = yield botbuilder.TeamsInfo.getMember(context, context.activity.from.id);
|
|
1410
|
+
internalLogger.verbose("Get Teams member account user principal name: " + account.userPrincipalName);
|
|
1411
|
+
const loginHint = account.userPrincipalName ? account.userPrincipalName : "";
|
|
1412
|
+
const signInResource = this.getSignInResource(loginHint);
|
|
1413
|
+
const card = botbuilder.CardFactory.oauthCard("", "Teams SSO Sign In", "Sign In", signInResource.signInLink, signInResource.tokenExchangeResource);
|
|
1414
|
+
card.content.buttons[0].type = botbuilder.ActionTypes.Signin;
|
|
1415
|
+
const msg = botbuilder.MessageFactory.attachment(card);
|
|
1416
|
+
// Send prompt
|
|
1417
|
+
yield context.sendActivity(msg);
|
|
1502
1418
|
});
|
|
1503
|
-
}
|
|
1419
|
+
}
|
|
1504
1420
|
/**
|
|
1505
1421
|
* Get sign in resource.
|
|
1506
1422
|
*
|
|
@@ -1508,10 +1424,10 @@ var TeamsBotSsoPrompt = /** @class */ (function (_super) {
|
|
|
1508
1424
|
*
|
|
1509
1425
|
* @internal
|
|
1510
1426
|
*/
|
|
1511
|
-
|
|
1427
|
+
getSignInResource(loginHint) {
|
|
1512
1428
|
var _a, _b, _c, _d, _e;
|
|
1513
1429
|
internalLogger.verbose("Get sign in authentication configuration");
|
|
1514
|
-
|
|
1430
|
+
const missingConfigurations = [];
|
|
1515
1431
|
if (!((_a = config === null || config === void 0 ? void 0 : config.authentication) === null || _a === void 0 ? void 0 : _a.initiateLoginEndpoint)) {
|
|
1516
1432
|
missingConfigurations.push("initiateLoginEndpoint");
|
|
1517
1433
|
}
|
|
@@ -1525,13 +1441,13 @@ var TeamsBotSsoPrompt = /** @class */ (function (_super) {
|
|
|
1525
1441
|
missingConfigurations.push("applicationIdUri");
|
|
1526
1442
|
}
|
|
1527
1443
|
if (missingConfigurations.length != 0) {
|
|
1528
|
-
|
|
1444
|
+
const errorMsg = formatString(ErrorMessage.InvalidConfiguration, missingConfigurations.join(", "), "undefined");
|
|
1529
1445
|
internalLogger.error(errorMsg);
|
|
1530
1446
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidConfiguration);
|
|
1531
1447
|
}
|
|
1532
|
-
|
|
1448
|
+
const signInLink = `${config.authentication.initiateLoginEndpoint}?scope=${encodeURI(this.settings.scopes.join(" "))}&clientId=${config.authentication.clientId}&tenantId=${config.authentication.tenantId}&loginHint=${loginHint}`;
|
|
1533
1449
|
internalLogger.verbose("Sign in link: " + signInLink);
|
|
1534
|
-
|
|
1450
|
+
const tokenExchangeResource = {
|
|
1535
1451
|
id: uuid.v4(),
|
|
1536
1452
|
uri: ((_e = config.authentication) === null || _e === void 0 ? void 0 : _e.applicationIdUri.replace(/\/$/, "")) + "/access_as_user",
|
|
1537
1453
|
};
|
|
@@ -1540,108 +1456,88 @@ var TeamsBotSsoPrompt = /** @class */ (function (_super) {
|
|
|
1540
1456
|
signInLink: signInLink,
|
|
1541
1457
|
tokenExchangeResource: tokenExchangeResource,
|
|
1542
1458
|
};
|
|
1543
|
-
}
|
|
1459
|
+
}
|
|
1544
1460
|
/**
|
|
1545
1461
|
* @internal
|
|
1546
1462
|
*/
|
|
1547
|
-
|
|
1548
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
ssoToken: ssoToken,
|
|
1580
|
-
ssoTokenExpiration: new Date(ssoTokenExpiration * 1000).toISOString(),
|
|
1581
|
-
connectionName: "",
|
|
1582
|
-
token: exchangedToken.token,
|
|
1583
|
-
expiration: exchangedToken.expiresOnTimestamp.toString(),
|
|
1584
|
-
};
|
|
1585
|
-
_a.label = 6;
|
|
1586
|
-
case 6: return [3 /*break*/, 9];
|
|
1587
|
-
case 7:
|
|
1588
|
-
_a.sent();
|
|
1589
|
-
warningMsg = "The bot is unable to exchange token. Ask for user consent.";
|
|
1463
|
+
recognizeToken(dc) {
|
|
1464
|
+
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
1465
|
+
const context = dc.context;
|
|
1466
|
+
let tokenResponse;
|
|
1467
|
+
if (this.isTokenExchangeRequestInvoke(context)) {
|
|
1468
|
+
internalLogger.verbose("Receive token exchange request");
|
|
1469
|
+
// Received activity is not a token exchange request
|
|
1470
|
+
if (!(context.activity.value && this.isTokenExchangeRequest(context.activity.value))) {
|
|
1471
|
+
const warningMsg = "The bot received an InvokeActivity that is missing a TokenExchangeInvokeRequest value. This is required to be sent with the InvokeActivity.";
|
|
1472
|
+
internalLogger.warn(warningMsg);
|
|
1473
|
+
yield context.sendActivity(this.getTokenExchangeInvokeResponse(botbuilder.StatusCodes.BAD_REQUEST, warningMsg));
|
|
1474
|
+
}
|
|
1475
|
+
else {
|
|
1476
|
+
const ssoToken = context.activity.value.token;
|
|
1477
|
+
const credential = new OnBehalfOfUserCredential(ssoToken);
|
|
1478
|
+
let exchangedToken;
|
|
1479
|
+
try {
|
|
1480
|
+
exchangedToken = yield credential.getToken(this.settings.scopes);
|
|
1481
|
+
if (exchangedToken) {
|
|
1482
|
+
yield context.sendActivity(this.getTokenExchangeInvokeResponse(botbuilder.StatusCodes.OK, "", context.activity.value.id));
|
|
1483
|
+
const ssoTokenExpiration = parseJwt(ssoToken).exp;
|
|
1484
|
+
tokenResponse = {
|
|
1485
|
+
ssoToken: ssoToken,
|
|
1486
|
+
ssoTokenExpiration: new Date(ssoTokenExpiration * 1000).toISOString(),
|
|
1487
|
+
connectionName: "",
|
|
1488
|
+
token: exchangedToken.token,
|
|
1489
|
+
expiration: exchangedToken.expiresOnTimestamp.toString(),
|
|
1490
|
+
};
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
catch (error) {
|
|
1494
|
+
const warningMsg = "The bot is unable to exchange token. Ask for user consent.";
|
|
1590
1495
|
internalLogger.info(warningMsg);
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
_a.sent();
|
|
1594
|
-
return [3 /*break*/, 9];
|
|
1595
|
-
case 9: return [3 /*break*/, 13];
|
|
1596
|
-
case 10:
|
|
1597
|
-
if (!this.isTeamsVerificationInvoke(context)) return [3 /*break*/, 13];
|
|
1598
|
-
internalLogger.verbose("Receive Teams state verification request");
|
|
1599
|
-
return [4 /*yield*/, this.sendOAuthCardAsync(dc.context)];
|
|
1600
|
-
case 11:
|
|
1601
|
-
_a.sent();
|
|
1602
|
-
return [4 /*yield*/, context.sendActivity({ type: invokeResponseType, value: { status: botbuilder.StatusCodes.OK } })];
|
|
1603
|
-
case 12:
|
|
1604
|
-
_a.sent();
|
|
1605
|
-
_a.label = 13;
|
|
1606
|
-
case 13: return [2 /*return*/, tokenResponse !== undefined
|
|
1607
|
-
? { succeeded: true, value: tokenResponse }
|
|
1608
|
-
: { succeeded: false }];
|
|
1496
|
+
yield context.sendActivity(this.getTokenExchangeInvokeResponse(botbuilder.StatusCodes.PRECONDITION_FAILED, warningMsg, context.activity.value.id));
|
|
1497
|
+
}
|
|
1609
1498
|
}
|
|
1610
|
-
}
|
|
1499
|
+
}
|
|
1500
|
+
else if (this.isTeamsVerificationInvoke(context)) {
|
|
1501
|
+
internalLogger.verbose("Receive Teams state verification request");
|
|
1502
|
+
yield this.sendOAuthCardAsync(dc.context);
|
|
1503
|
+
yield context.sendActivity({ type: invokeResponseType, value: { status: botbuilder.StatusCodes.OK } });
|
|
1504
|
+
}
|
|
1505
|
+
return tokenResponse !== undefined
|
|
1506
|
+
? { succeeded: true, value: tokenResponse }
|
|
1507
|
+
: { succeeded: false };
|
|
1611
1508
|
});
|
|
1612
|
-
}
|
|
1509
|
+
}
|
|
1613
1510
|
/**
|
|
1614
1511
|
* @internal
|
|
1615
1512
|
*/
|
|
1616
|
-
|
|
1617
|
-
|
|
1513
|
+
getTokenExchangeInvokeResponse(status, failureDetail, id) {
|
|
1514
|
+
const invokeResponse = {
|
|
1618
1515
|
type: invokeResponseType,
|
|
1619
|
-
value: { status
|
|
1516
|
+
value: { status, body: new TokenExchangeInvokeResponse(id, failureDetail) },
|
|
1620
1517
|
};
|
|
1621
1518
|
return invokeResponse;
|
|
1622
|
-
}
|
|
1519
|
+
}
|
|
1623
1520
|
/**
|
|
1624
1521
|
* @internal
|
|
1625
1522
|
*/
|
|
1626
|
-
|
|
1627
|
-
|
|
1523
|
+
isTeamsVerificationInvoke(context) {
|
|
1524
|
+
const activity = context.activity;
|
|
1628
1525
|
return activity.type === botbuilder.ActivityTypes.Invoke && activity.name === botbuilder.verifyStateOperationName;
|
|
1629
|
-
}
|
|
1526
|
+
}
|
|
1630
1527
|
/**
|
|
1631
1528
|
* @internal
|
|
1632
1529
|
*/
|
|
1633
|
-
|
|
1634
|
-
|
|
1530
|
+
isTokenExchangeRequestInvoke(context) {
|
|
1531
|
+
const activity = context.activity;
|
|
1635
1532
|
return activity.type === botbuilder.ActivityTypes.Invoke && activity.name === botbuilder.tokenExchangeOperationName;
|
|
1636
|
-
}
|
|
1533
|
+
}
|
|
1637
1534
|
/**
|
|
1638
1535
|
* @internal
|
|
1639
1536
|
*/
|
|
1640
|
-
|
|
1537
|
+
isTokenExchangeRequest(obj) {
|
|
1641
1538
|
return obj.hasOwnProperty("token");
|
|
1642
|
-
}
|
|
1643
|
-
|
|
1644
|
-
}(botbuilderDialogs.Dialog));
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1645
1541
|
|
|
1646
1542
|
exports.DefaultTediousConnectionConfiguration = DefaultTediousConnectionConfiguration;
|
|
1647
1543
|
exports.ErrorWithCode = ErrorWithCode;
|