@microsoft/teamsfx 0.2.8-alpha.9ef5081b.0 → 0.2.8-alpha.b4c7969d.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/dist/index.js +87 -35
- package/dist/index.js.map +1 -1
- package/dist/teamsfx.js +1 -1
- package/dist/teamsfx.js.map +1 -1
- package/dist-esm/src/core/errors.js +4 -0
- package/dist-esm/src/core/errors.js.map +1 -1
- package/dist-esm/src/credential/m365TenantCredential.js +19 -21
- package/dist-esm/src/credential/m365TenantCredential.js.map +1 -1
- package/dist-esm/src/credential/onBehalfOfUserCredential.js +8 -17
- package/dist-esm/src/credential/onBehalfOfUserCredential.js.map +1 -1
- package/dist-esm/src/models/configuration.js.map +1 -1
- package/dist-esm/src/util/utils.js +38 -0
- package/dist-esm/src/util/utils.js.map +1 -1
- package/dist-esm/src/util/utils.node.js +23 -0
- package/dist-esm/src/util/utils.node.js.map +1 -0
- package/package.json +4 -5
- package/types/teamsfx.d.ts +12 -2
package/dist/index.js
CHANGED
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var tslib = require('tslib');
|
|
6
|
-
var identity = require('@azure/identity');
|
|
7
6
|
var jwt_decode = require('jwt-decode');
|
|
7
|
+
var crypto = require('crypto');
|
|
8
8
|
var coreHttp = require('@azure/core-http');
|
|
9
9
|
var msalNode = require('@azure/msal-node');
|
|
10
10
|
var botbuilder = require('botbuilder');
|
|
11
11
|
var botbuilderDialogs = require('botbuilder-dialogs');
|
|
12
12
|
var uuid = require('uuid');
|
|
13
13
|
var microsoftGraphClient = require('@microsoft/microsoft-graph-client');
|
|
14
|
+
var identity = require('@azure/identity');
|
|
14
15
|
|
|
15
16
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
16
17
|
|
|
@@ -32,6 +33,10 @@ exports.ErrorCode = void 0;
|
|
|
32
33
|
* Invalid configuration error.
|
|
33
34
|
*/
|
|
34
35
|
ErrorCode["InvalidConfiguration"] = "InvalidConfiguration";
|
|
36
|
+
/**
|
|
37
|
+
* Invalid certificate error.
|
|
38
|
+
*/
|
|
39
|
+
ErrorCode["InvalidCertificate"] = "InvalidCertificate";
|
|
35
40
|
/**
|
|
36
41
|
* Internal error.
|
|
37
42
|
*/
|
|
@@ -330,6 +335,43 @@ function validateScopesType(value) {
|
|
|
330
335
|
internalLogger.error(errorMsg);
|
|
331
336
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidParameter);
|
|
332
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* @internal
|
|
340
|
+
*/
|
|
341
|
+
function getScopesArray(scopes) {
|
|
342
|
+
const scopesArray = typeof scopes === "string" ? scopes.split(" ") : scopes;
|
|
343
|
+
return scopesArray.filter((x) => x !== null && x !== "");
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* @internal
|
|
347
|
+
*/
|
|
348
|
+
function getAuthority(authorityHost, tenantId) {
|
|
349
|
+
const normalizedAuthorityHost = authorityHost.replace(/\/+$/g, "");
|
|
350
|
+
return normalizedAuthorityHost + "/" + tenantId;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* @internal
|
|
354
|
+
*/
|
|
355
|
+
function parseCertificate(certificateContent) {
|
|
356
|
+
if (!certificateContent) {
|
|
357
|
+
return undefined;
|
|
358
|
+
}
|
|
359
|
+
const certificatePattern = /(-+BEGIN CERTIFICATE-+)(\n\r?|\r\n?)([A-Za-z0-9+/\n\r]+=*)(\n\r?|\r\n?)(-+END CERTIFICATE-+)/;
|
|
360
|
+
const match = certificatePattern.exec(certificateContent);
|
|
361
|
+
if (!match) {
|
|
362
|
+
const errorMsg = "The certificate content does not contain a PEM-encoded certificate.";
|
|
363
|
+
internalLogger.error(errorMsg);
|
|
364
|
+
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidCertificate);
|
|
365
|
+
}
|
|
366
|
+
const thumbprint = crypto.createHash("sha1")
|
|
367
|
+
.update(Buffer.from(match[3], "base64"))
|
|
368
|
+
.digest("hex")
|
|
369
|
+
.toUpperCase();
|
|
370
|
+
return {
|
|
371
|
+
thumbprint: thumbprint,
|
|
372
|
+
privateKey: certificateContent,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
333
375
|
|
|
334
376
|
// Copyright (c) Microsoft Corporation.
|
|
335
377
|
// Licensed under the MIT license.
|
|
@@ -469,6 +511,27 @@ function getAuthenticationConfiguration() {
|
|
|
469
511
|
throw new ErrorWithCode(formatString(ErrorMessage.ConfigurationNotExists, errorMsg), exports.ErrorCode.InvalidConfiguration);
|
|
470
512
|
}
|
|
471
513
|
|
|
514
|
+
/**
|
|
515
|
+
* @internal
|
|
516
|
+
*/
|
|
517
|
+
function createConfidentialClientApplication(authentication) {
|
|
518
|
+
const authority = getAuthority(authentication.authorityHost, authentication.tenantId);
|
|
519
|
+
const clientCertificate = parseCertificate(authentication.certificateContent);
|
|
520
|
+
const auth = {
|
|
521
|
+
clientId: authentication.clientId,
|
|
522
|
+
authority: authority,
|
|
523
|
+
};
|
|
524
|
+
if (clientCertificate) {
|
|
525
|
+
auth.clientCertificate = clientCertificate;
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
auth.clientSecret = authentication.clientSecret;
|
|
529
|
+
}
|
|
530
|
+
return new msalNode.ConfidentialClientApplication({
|
|
531
|
+
auth,
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
|
|
472
535
|
// Copyright (c) Microsoft Corporation.
|
|
473
536
|
/**
|
|
474
537
|
* Represent Microsoft 365 tenant identity, and it is usually used when user is not involved like time-triggered automation job.
|
|
@@ -499,10 +562,7 @@ class M365TenantCredential {
|
|
|
499
562
|
constructor() {
|
|
500
563
|
internalLogger.info("Create M365 tenant credential");
|
|
501
564
|
const config = this.loadAndValidateConfig();
|
|
502
|
-
|
|
503
|
-
authorityHost: config.authorityHost,
|
|
504
|
-
};
|
|
505
|
-
this.clientSecretCredential = new identity.ClientSecretCredential(config.tenantId, config.clientId, config.clientSecret, tokenCredentialOptions);
|
|
565
|
+
this.msalClient = createConfidentialClientApplication(config);
|
|
506
566
|
}
|
|
507
567
|
/**
|
|
508
568
|
* Get access token for credential.
|
|
@@ -537,20 +597,21 @@ class M365TenantCredential {
|
|
|
537
597
|
const scopesStr = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
538
598
|
internalLogger.info("Get access token with scopes: " + scopesStr);
|
|
539
599
|
try {
|
|
540
|
-
|
|
600
|
+
const scopesArray = getScopesArray(scopes);
|
|
601
|
+
const authenticationResult = yield this.msalClient.acquireTokenByClientCredential({
|
|
602
|
+
scopes: scopesArray,
|
|
603
|
+
});
|
|
604
|
+
if (authenticationResult) {
|
|
605
|
+
accessToken = {
|
|
606
|
+
token: authenticationResult.accessToken,
|
|
607
|
+
expiresOnTimestamp: authenticationResult.expiresOn.getTime(),
|
|
608
|
+
};
|
|
609
|
+
}
|
|
541
610
|
}
|
|
542
611
|
catch (err) {
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
internalLogger.error(errorMsg);
|
|
547
|
-
throw new ErrorWithCode(errorMsg, exports.ErrorCode.ServiceError);
|
|
548
|
-
}
|
|
549
|
-
else {
|
|
550
|
-
const errorMsg = "Get M365 tenant credential failed with error: " + err.message;
|
|
551
|
-
internalLogger.error(errorMsg);
|
|
552
|
-
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InternalError);
|
|
553
|
-
}
|
|
612
|
+
const errorMsg = "Get M365 tenant credential failed with error: " + err.message;
|
|
613
|
+
internalLogger.error(errorMsg);
|
|
614
|
+
throw new ErrorWithCode(errorMsg, exports.ErrorCode.ServiceError);
|
|
554
615
|
}
|
|
555
616
|
if (!accessToken) {
|
|
556
617
|
const errorMsg = "Get M365 tenant credential access token failed with empty access token";
|
|
@@ -571,15 +632,15 @@ class M365TenantCredential {
|
|
|
571
632
|
internalLogger.error(ErrorMessage.AuthenticationConfigurationNotExists);
|
|
572
633
|
throw new ErrorWithCode(ErrorMessage.AuthenticationConfigurationNotExists, exports.ErrorCode.InvalidConfiguration);
|
|
573
634
|
}
|
|
574
|
-
if (config.clientId && config.clientSecret && config.tenantId) {
|
|
635
|
+
if (config.clientId && (config.clientSecret || config.certificateContent) && config.tenantId) {
|
|
575
636
|
return config;
|
|
576
637
|
}
|
|
577
638
|
const missingValues = [];
|
|
578
639
|
if (!config.clientId) {
|
|
579
640
|
missingValues.push("clientId");
|
|
580
641
|
}
|
|
581
|
-
if (!config.clientSecret) {
|
|
582
|
-
missingValues.push("clientSecret");
|
|
642
|
+
if (!config.clientSecret && !config.certificateContent) {
|
|
643
|
+
missingValues.push("clientSecret or certificateContent");
|
|
583
644
|
}
|
|
584
645
|
if (!config.tenantId) {
|
|
585
646
|
missingValues.push("tenantId");
|
|
@@ -614,7 +675,7 @@ class OnBehalfOfUserCredential {
|
|
|
614
675
|
*
|
|
615
676
|
* @param {string} ssoToken - User token provided by Teams SSO feature.
|
|
616
677
|
*
|
|
617
|
-
* @throws {@link ErrorCode|InvalidConfiguration} when client id, client secret, authority host or tenant id is not found in config.
|
|
678
|
+
* @throws {@link ErrorCode|InvalidConfiguration} when client id, client secret, certificate content, authority host or tenant id is not found in config.
|
|
618
679
|
* @throws {@link ErrorCode|InternalError} when SSO token is not valid.
|
|
619
680
|
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is browser.
|
|
620
681
|
*
|
|
@@ -630,10 +691,10 @@ class OnBehalfOfUserCredential {
|
|
|
630
691
|
if (!((_b = config === null || config === void 0 ? void 0 : config.authentication) === null || _b === void 0 ? void 0 : _b.authorityHost)) {
|
|
631
692
|
missingConfigurations.push("authorityHost");
|
|
632
693
|
}
|
|
633
|
-
if (!((_c = config === null || config === void 0 ? void 0 : config.authentication) === null || _c === void 0 ? void 0 : _c.clientSecret)) {
|
|
634
|
-
missingConfigurations.push("clientSecret");
|
|
694
|
+
if (!((_c = config === null || config === void 0 ? void 0 : config.authentication) === null || _c === void 0 ? void 0 : _c.clientSecret) && !((_d = config === null || config === void 0 ? void 0 : config.authentication) === null || _d === void 0 ? void 0 : _d.certificateContent)) {
|
|
695
|
+
missingConfigurations.push("clientSecret or certificateContent");
|
|
635
696
|
}
|
|
636
|
-
if (!((
|
|
697
|
+
if (!((_e = config === null || config === void 0 ? void 0 : config.authentication) === null || _e === void 0 ? void 0 : _e.tenantId)) {
|
|
637
698
|
missingConfigurations.push("tenantId");
|
|
638
699
|
}
|
|
639
700
|
if (missingConfigurations.length != 0) {
|
|
@@ -641,15 +702,7 @@ class OnBehalfOfUserCredential {
|
|
|
641
702
|
internalLogger.error(errorMsg);
|
|
642
703
|
throw new ErrorWithCode(errorMsg, exports.ErrorCode.InvalidConfiguration);
|
|
643
704
|
}
|
|
644
|
-
|
|
645
|
-
const authority = normalizedAuthorityHost + "/" + ((_e = config.authentication) === null || _e === void 0 ? void 0 : _e.tenantId);
|
|
646
|
-
this.msalClient = new msalNode.ConfidentialClientApplication({
|
|
647
|
-
auth: {
|
|
648
|
-
clientId: config.authentication.clientId,
|
|
649
|
-
authority: authority,
|
|
650
|
-
clientSecret: config.authentication.clientSecret,
|
|
651
|
-
},
|
|
652
|
-
});
|
|
705
|
+
this.msalClient = createConfidentialClientApplication(config.authentication);
|
|
653
706
|
const decodedSsoToken = parseJwt(ssoToken);
|
|
654
707
|
this.ssoToken = {
|
|
655
708
|
token: ssoToken,
|
|
@@ -694,8 +747,7 @@ class OnBehalfOfUserCredential {
|
|
|
694
747
|
getToken(scopes, options) {
|
|
695
748
|
return tslib.__awaiter(this, void 0, void 0, function* () {
|
|
696
749
|
validateScopesType(scopes);
|
|
697
|
-
|
|
698
|
-
scopesArray = scopesArray.filter((x) => x !== null && x !== "");
|
|
750
|
+
const scopesArray = getScopesArray(scopes);
|
|
699
751
|
let result;
|
|
700
752
|
if (!scopesArray.length) {
|
|
701
753
|
internalLogger.info("Get SSO token.");
|