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