@microsoft/teamsfx 0.4.1-alpha.fcc60ca0.0 → 0.4.2-alpha.01e159e5.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 +147 -220
- 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 +355 -549
- 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 +12 -9
- package/types/teamsfx.d.ts +8 -2
package/README.md
CHANGED
|
@@ -45,7 +45,6 @@ Please note that you need to load configuration before using any credentials.
|
|
|
45
45
|
loadConfiguration({
|
|
46
46
|
authentication: {
|
|
47
47
|
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
48
|
-
simpleAuthEndpoint: process.env.REACT_APP_TEAMSFX_ENDPOINT,
|
|
49
48
|
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
50
49
|
},
|
|
51
50
|
});
|
|
@@ -67,7 +66,6 @@ Use the snippet below:
|
|
|
67
66
|
loadConfiguration({
|
|
68
67
|
authentication: {
|
|
69
68
|
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
70
|
-
simpleAuthEndpoint: process.env.REACT_APP_TEAMSFX_ENDPOINT,
|
|
71
69
|
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
72
70
|
},
|
|
73
71
|
});
|
|
@@ -165,7 +163,6 @@ Use `TeamsUserCredential` and `createMicrosoftGraphClient`.
|
|
|
165
163
|
loadConfiguration({
|
|
166
164
|
authentication: {
|
|
167
165
|
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
168
|
-
simpleAuthEndpoint: process.env.REACT_APP_TEAMSFX_ENDPOINT,
|
|
169
166
|
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
170
167
|
},
|
|
171
168
|
});
|
|
@@ -182,7 +179,6 @@ Use `axios` library to make HTTP request to Azure Function.
|
|
|
182
179
|
loadConfiguration({
|
|
183
180
|
authentication: {
|
|
184
181
|
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
185
|
-
simpleAuthEndpoint: process.env.REACT_APP_TEAMSFX_ENDPOINT,
|
|
186
182
|
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
187
183
|
},
|
|
188
184
|
});
|
|
@@ -205,7 +201,10 @@ Apart from `tedious`, you can also compose connection config of other SQL librar
|
|
|
205
201
|
```ts
|
|
206
202
|
loadConfiguration();
|
|
207
203
|
const sqlConnectConfig = new DefaultTediousConnectionConfiguration();
|
|
204
|
+
// if there's only one SQL database
|
|
208
205
|
const config = await sqlConnectConfig.getConfig();
|
|
206
|
+
// if there are multiple SQL databases
|
|
207
|
+
const config2 = await sqlConnectionConfig.getConfig("your database name");
|
|
209
208
|
const connection = new Connection(config);
|
|
210
209
|
connection.on("connect", (error) => {
|
|
211
210
|
if (error) {
|
package/dist/index.esm2017.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import jwt_decode from 'jwt-decode';
|
|
2
2
|
import * as microsoftTeams from '@microsoft/teams-js';
|
|
3
|
-
import
|
|
3
|
+
import { PublicClientApplication } from '@azure/msal-browser';
|
|
4
4
|
import { Client } from '@microsoft/microsoft-graph-client';
|
|
5
5
|
|
|
6
6
|
// Copyright (c) Microsoft Corporation.
|
|
@@ -55,6 +55,10 @@ var ErrorCode;
|
|
|
55
55
|
* Operation failed.
|
|
56
56
|
*/
|
|
57
57
|
ErrorCode["FailedOperation"] = "FailedOperation";
|
|
58
|
+
/**
|
|
59
|
+
* Invalid response error.
|
|
60
|
+
*/
|
|
61
|
+
ErrorCode["InvalidResponse"] = "InvalidResponse";
|
|
58
62
|
})(ErrorCode || (ErrorCode = {}));
|
|
59
63
|
/**
|
|
60
64
|
* @internal
|
|
@@ -309,6 +313,57 @@ function getUserInfoFromSsoToken(ssoToken) {
|
|
|
309
313
|
}
|
|
310
314
|
return userInfo;
|
|
311
315
|
}
|
|
316
|
+
/**
|
|
317
|
+
* @internal
|
|
318
|
+
*/
|
|
319
|
+
function getTenantIdAndLoginHintFromSsoToken(ssoToken) {
|
|
320
|
+
if (!ssoToken) {
|
|
321
|
+
const errorMsg = "SSO token is undefined.";
|
|
322
|
+
internalLogger.error(errorMsg);
|
|
323
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidParameter);
|
|
324
|
+
}
|
|
325
|
+
const tokenObject = parseJwt(ssoToken);
|
|
326
|
+
const userInfo = {
|
|
327
|
+
tid: tokenObject.tid,
|
|
328
|
+
loginHint: tokenObject.ver === "2.0"
|
|
329
|
+
? tokenObject.preferred_username
|
|
330
|
+
: tokenObject.upn,
|
|
331
|
+
};
|
|
332
|
+
return userInfo;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* @internal
|
|
336
|
+
*/
|
|
337
|
+
function parseAccessTokenFromAuthCodeTokenResponse(tokenResponse) {
|
|
338
|
+
try {
|
|
339
|
+
const tokenResponseObject = typeof tokenResponse == "string"
|
|
340
|
+
? JSON.parse(tokenResponse)
|
|
341
|
+
: tokenResponse;
|
|
342
|
+
if (!tokenResponseObject || !tokenResponseObject.accessToken) {
|
|
343
|
+
const errorMsg = "Get empty access token from Auth Code token response.";
|
|
344
|
+
internalLogger.error(errorMsg);
|
|
345
|
+
throw new Error(errorMsg);
|
|
346
|
+
}
|
|
347
|
+
const token = tokenResponseObject.accessToken;
|
|
348
|
+
const tokenObject = parseJwt(token);
|
|
349
|
+
if (tokenObject.ver !== "1.0" && tokenObject.ver !== "2.0") {
|
|
350
|
+
const errorMsg = "SSO token is not valid with an unknown version: " + tokenObject.ver;
|
|
351
|
+
internalLogger.error(errorMsg);
|
|
352
|
+
throw new Error(errorMsg);
|
|
353
|
+
}
|
|
354
|
+
const accessToken = {
|
|
355
|
+
token: token,
|
|
356
|
+
expiresOnTimestamp: tokenObject.exp * 1000,
|
|
357
|
+
};
|
|
358
|
+
return accessToken;
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
const errorMsg = "Parse access token failed from Auth Code token response in node env with error: " +
|
|
362
|
+
error.message;
|
|
363
|
+
internalLogger.error(errorMsg);
|
|
364
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.InternalError);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
312
367
|
/**
|
|
313
368
|
* Format string template with replacements
|
|
314
369
|
*
|
|
@@ -548,43 +603,10 @@ class OnBehalfOfUserCredential {
|
|
|
548
603
|
}
|
|
549
604
|
|
|
550
605
|
// Copyright (c) Microsoft Corporation.
|
|
551
|
-
// Licensed under the MIT license.
|
|
552
|
-
/**
|
|
553
|
-
* Configuration used in initialization.
|
|
554
|
-
* @internal
|
|
555
|
-
*/
|
|
556
|
-
class Cache {
|
|
557
|
-
static get(key) {
|
|
558
|
-
return sessionStorage.getItem(key);
|
|
559
|
-
}
|
|
560
|
-
static set(key, value) {
|
|
561
|
-
sessionStorage.setItem(key, value);
|
|
562
|
-
}
|
|
563
|
-
static remove(key) {
|
|
564
|
-
sessionStorage.removeItem(key);
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
// Copyright (c) Microsoft Corporation.
|
|
569
|
-
// Licensed under the MIT license.
|
|
570
|
-
/**
|
|
571
|
-
* @internal
|
|
572
|
-
*/
|
|
573
|
-
var GrantType;
|
|
574
|
-
(function (GrantType) {
|
|
575
|
-
GrantType["authCode"] = "authorization_code";
|
|
576
|
-
GrantType["ssoToken"] = "sso_token";
|
|
577
|
-
})(GrantType || (GrantType = {}));
|
|
578
|
-
|
|
579
|
-
// Copyright (c) Microsoft Corporation.
|
|
580
|
-
const accessTokenCacheKeyPrefix = "accessToken";
|
|
581
|
-
const separator = "-";
|
|
582
606
|
const tokenRefreshTimeSpanInMillisecond = 5 * 60 * 1000;
|
|
583
607
|
const initializeTeamsSdkTimeoutInMillisecond = 5000;
|
|
584
608
|
const loginPageWidth = 600;
|
|
585
609
|
const loginPageHeight = 535;
|
|
586
|
-
const maxRetryCount = 3;
|
|
587
|
-
const retryTimeSpanInMillisecond = 3000;
|
|
588
610
|
/**
|
|
589
611
|
* Represent Teams current user's identity, and it is used within Teams tab application.
|
|
590
612
|
*
|
|
@@ -602,7 +624,6 @@ class TeamsUserCredential {
|
|
|
602
624
|
* ```typescript
|
|
603
625
|
* const config = {
|
|
604
626
|
* authentication: {
|
|
605
|
-
* runtimeConnectorEndpoint: "https://xxx.xxx.com",
|
|
606
627
|
* initiateLoginEndpoint: "https://localhost:3000/auth-start.html",
|
|
607
628
|
* clientId: "xxx"
|
|
608
629
|
* }
|
|
@@ -620,6 +641,7 @@ class TeamsUserCredential {
|
|
|
620
641
|
internalLogger.info("Create teams user credential");
|
|
621
642
|
this.config = this.loadAndValidateConfig();
|
|
622
643
|
this.ssoToken = null;
|
|
644
|
+
this.initialized = false;
|
|
623
645
|
}
|
|
624
646
|
/**
|
|
625
647
|
* Popup login page to get user's access token with specific scopes.
|
|
@@ -637,7 +659,6 @@ class TeamsUserCredential {
|
|
|
637
659
|
* @param scopes - The list of scopes for which the token will have access, before that, we will request user to consent.
|
|
638
660
|
*
|
|
639
661
|
* @throws {@link ErrorCode|InternalError} when failed to login with unknown error.
|
|
640
|
-
* @throws {@link ErrorCode|ServiceError} when simple auth server failed to exchange access token.
|
|
641
662
|
* @throws {@link ErrorCode|ConsentFailed} when user canceled or failed to consent.
|
|
642
663
|
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
643
664
|
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
@@ -648,27 +669,45 @@ class TeamsUserCredential {
|
|
|
648
669
|
validateScopesType(scopes);
|
|
649
670
|
const scopesStr = typeof scopes === "string" ? scopes : scopes.join(" ");
|
|
650
671
|
internalLogger.info(`Popup login page to get user's access token with scopes: ${scopesStr}`);
|
|
672
|
+
if (!this.initialized) {
|
|
673
|
+
await this.init();
|
|
674
|
+
}
|
|
651
675
|
return new Promise((resolve, reject) => {
|
|
652
676
|
microsoftTeams.initialize(() => {
|
|
653
677
|
microsoftTeams.authentication.authenticate({
|
|
654
|
-
url: `${this.config.initiateLoginEndpoint}?clientId=${this.config.clientId}&scope=${encodeURI(scopesStr)}`,
|
|
678
|
+
url: `${this.config.initiateLoginEndpoint}?clientId=${this.config.clientId}&scope=${encodeURI(scopesStr)}&loginHint=${this.loginHint}`,
|
|
655
679
|
width: loginPageWidth,
|
|
656
680
|
height: loginPageHeight,
|
|
657
681
|
successCallback: async (result) => {
|
|
658
682
|
if (!result) {
|
|
659
|
-
const errorMsg = "Get empty authentication result from
|
|
683
|
+
const errorMsg = "Get empty authentication result from MSAL";
|
|
660
684
|
internalLogger.error(errorMsg);
|
|
661
685
|
reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
|
|
662
686
|
return;
|
|
663
687
|
}
|
|
664
|
-
|
|
688
|
+
let resultJson = {};
|
|
665
689
|
try {
|
|
666
|
-
|
|
667
|
-
|
|
690
|
+
resultJson = JSON.parse(result);
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
// If can not parse result as Json, will throw error.
|
|
694
|
+
const failedToParseResult = "Failed to parse response to Json.";
|
|
695
|
+
internalLogger.error(failedToParseResult);
|
|
696
|
+
reject(new ErrorWithCode(failedToParseResult, ErrorCode.InvalidResponse));
|
|
668
697
|
}
|
|
669
|
-
|
|
670
|
-
|
|
698
|
+
// If code exists in result, user may using previous auth-start and auth-end page.
|
|
699
|
+
if (resultJson.code) {
|
|
700
|
+
const helpLink = "https://aka.ms/teamsfx-auth-code-flow";
|
|
701
|
+
const usingPreviousAuthPage = "Found auth code in response. Auth code is not support for current version of SDK. " +
|
|
702
|
+
`Please refer to the help link for how to fix the issue: ${helpLink}.`;
|
|
703
|
+
internalLogger.error(usingPreviousAuthPage);
|
|
704
|
+
reject(new ErrorWithCode(usingPreviousAuthPage, ErrorCode.InvalidResponse));
|
|
671
705
|
}
|
|
706
|
+
// If sessionStorage exists in result, set the values in current session storage.
|
|
707
|
+
if (resultJson.sessionStorage) {
|
|
708
|
+
this.setSessionStorage(resultJson.sessionStorage);
|
|
709
|
+
}
|
|
710
|
+
resolve();
|
|
672
711
|
},
|
|
673
712
|
failureCallback: (reason) => {
|
|
674
713
|
const errorMsg = `Consent failed for the scope ${scopesStr} with error: ${reason}`;
|
|
@@ -703,7 +742,6 @@ class TeamsUserCredential {
|
|
|
703
742
|
*
|
|
704
743
|
* @throws {@link ErrorCode|InternalError} when failed to get access token with unknown error.
|
|
705
744
|
* @throws {@link ErrorCode|UiRequiredError} when need user consent to get access token.
|
|
706
|
-
* @throws {@link ErrorCode|ServiceError} when failed to get access token from simple auth server.
|
|
707
745
|
* @throws {@link ErrorCode|InvalidParameter} when scopes is not a valid string or string array.
|
|
708
746
|
* @throws {@link ErrorCode|RuntimeNotSupported} when runtime is nodeJS.
|
|
709
747
|
*
|
|
@@ -724,21 +762,47 @@ class TeamsUserCredential {
|
|
|
724
762
|
}
|
|
725
763
|
else {
|
|
726
764
|
internalLogger.info("Get access token with scopes: " + scopeStr);
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
765
|
+
if (!this.initialized) {
|
|
766
|
+
await this.init();
|
|
767
|
+
}
|
|
768
|
+
let tokenResponse;
|
|
769
|
+
const scopesArray = typeof scopes === "string" ? scopes.split(" ") : scopes;
|
|
770
|
+
const domain = window.location.origin;
|
|
771
|
+
// First try to get Access Token from cache.
|
|
772
|
+
try {
|
|
773
|
+
const account = this.msalInstance.getAccountByUsername(this.loginHint);
|
|
774
|
+
const scopesRequestForAcquireTokenSilent = {
|
|
775
|
+
scopes: scopesArray,
|
|
776
|
+
account: account !== null && account !== void 0 ? account : undefined,
|
|
777
|
+
redirectUri: `${domain}/blank-auth-end.html`,
|
|
778
|
+
};
|
|
779
|
+
tokenResponse = await this.msalInstance.acquireTokenSilent(scopesRequestForAcquireTokenSilent);
|
|
780
|
+
}
|
|
781
|
+
catch (error) {
|
|
782
|
+
const acquireTokenSilentFailedMessage = `Failed to call acquireTokenSilent. Reason: ${error === null || error === void 0 ? void 0 : error.message}. `;
|
|
783
|
+
internalLogger.verbose(acquireTokenSilentFailedMessage);
|
|
784
|
+
}
|
|
785
|
+
if (!tokenResponse) {
|
|
786
|
+
// If fail to get Access Token from cache, try to get Access token by silent login.
|
|
787
|
+
try {
|
|
788
|
+
const scopesRequestForSsoSilent = {
|
|
789
|
+
scopes: scopesArray,
|
|
790
|
+
loginHint: this.loginHint,
|
|
791
|
+
redirectUri: `${domain}/blank-auth-end.html`,
|
|
792
|
+
};
|
|
793
|
+
tokenResponse = await this.msalInstance.ssoSilent(scopesRequestForSsoSilent);
|
|
733
794
|
}
|
|
734
|
-
|
|
735
|
-
|
|
795
|
+
catch (error) {
|
|
796
|
+
const ssoSilentFailedMessage = `Failed to call ssoSilent. Reason: ${error === null || error === void 0 ? void 0 : error.message}. `;
|
|
797
|
+
internalLogger.verbose(ssoSilentFailedMessage);
|
|
736
798
|
}
|
|
737
799
|
}
|
|
738
|
-
|
|
739
|
-
|
|
800
|
+
if (!tokenResponse) {
|
|
801
|
+
const errorMsg = `Failed to get access token cache silently, please login first: you need login first before get access token.`;
|
|
802
|
+
internalLogger.error(errorMsg);
|
|
803
|
+
throw new ErrorWithCode(errorMsg, ErrorCode.UiRequiredError);
|
|
740
804
|
}
|
|
741
|
-
const accessToken =
|
|
805
|
+
const accessToken = parseAccessTokenFromAuthCodeTokenResponse(tokenResponse);
|
|
742
806
|
return accessToken;
|
|
743
807
|
}
|
|
744
808
|
}
|
|
@@ -763,65 +827,22 @@ class TeamsUserCredential {
|
|
|
763
827
|
const ssoToken = await this.getSSOToken();
|
|
764
828
|
return getUserInfoFromSsoToken(ssoToken.token);
|
|
765
829
|
}
|
|
766
|
-
async
|
|
767
|
-
|
|
768
|
-
const
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
this.setTokenCache(key, {
|
|
783
|
-
token: tokenResult.access_token,
|
|
784
|
-
expiresOnTimestamp: tokenResult.expires_on,
|
|
785
|
-
});
|
|
786
|
-
return;
|
|
787
|
-
}
|
|
788
|
-
catch (err) {
|
|
789
|
-
if (((_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.type) && err.response.data.type === "AadUiRequiredException") {
|
|
790
|
-
internalLogger.warn("Exchange access token failed, retry...");
|
|
791
|
-
if (retryCount < maxRetryCount) {
|
|
792
|
-
await this.sleep(retryTimeSpanInMillisecond);
|
|
793
|
-
retryCount++;
|
|
794
|
-
continue;
|
|
795
|
-
}
|
|
796
|
-
}
|
|
797
|
-
throw err;
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* Get access token cache from authentication server
|
|
803
|
-
* @returns Access token
|
|
804
|
-
*/
|
|
805
|
-
async getAndCacheAccessTokenFromSimpleAuthServer(scopesStr) {
|
|
806
|
-
try {
|
|
807
|
-
internalLogger.verbose("Get access token from authentication server with scopes: " + scopesStr);
|
|
808
|
-
const axiosInstance = await this.getAxiosInstance();
|
|
809
|
-
const response = await axiosInstance.post("/auth/token", {
|
|
810
|
-
scope: scopesStr,
|
|
811
|
-
grant_type: GrantType.ssoToken,
|
|
812
|
-
});
|
|
813
|
-
const accessTokenResult = response.data;
|
|
814
|
-
const accessToken = {
|
|
815
|
-
token: accessTokenResult.access_token,
|
|
816
|
-
expiresOnTimestamp: accessTokenResult.expires_on,
|
|
817
|
-
};
|
|
818
|
-
const cacheKey = await this.getAccessTokenCacheKey(scopesStr);
|
|
819
|
-
this.setTokenCache(cacheKey, accessToken);
|
|
820
|
-
return accessToken;
|
|
821
|
-
}
|
|
822
|
-
catch (err) {
|
|
823
|
-
throw this.generateAuthServerError(err);
|
|
824
|
-
}
|
|
830
|
+
async init() {
|
|
831
|
+
const ssoToken = await this.getSSOToken();
|
|
832
|
+
const info = getTenantIdAndLoginHintFromSsoToken(ssoToken.token);
|
|
833
|
+
this.loginHint = info.loginHint;
|
|
834
|
+
this.tid = info.tid;
|
|
835
|
+
const msalConfig = {
|
|
836
|
+
auth: {
|
|
837
|
+
clientId: this.config.clientId,
|
|
838
|
+
authority: `https://login.microsoftonline.com/${this.tid}`,
|
|
839
|
+
},
|
|
840
|
+
cache: {
|
|
841
|
+
cacheLocation: "sessionStorage",
|
|
842
|
+
},
|
|
843
|
+
};
|
|
844
|
+
this.msalInstance = new PublicClientApplication(msalConfig);
|
|
845
|
+
this.initialized = true;
|
|
825
846
|
}
|
|
826
847
|
/**
|
|
827
848
|
* Get SSO token using teams SDK
|
|
@@ -891,16 +912,13 @@ class TeamsUserCredential {
|
|
|
891
912
|
internalLogger.error(ErrorMessage.AuthenticationConfigurationNotExists);
|
|
892
913
|
throw new ErrorWithCode(ErrorMessage.AuthenticationConfigurationNotExists, ErrorCode.InvalidConfiguration);
|
|
893
914
|
}
|
|
894
|
-
if (config.initiateLoginEndpoint && config.
|
|
915
|
+
if (config.initiateLoginEndpoint && config.clientId) {
|
|
895
916
|
return config;
|
|
896
917
|
}
|
|
897
918
|
const missingValues = [];
|
|
898
919
|
if (!config.initiateLoginEndpoint) {
|
|
899
920
|
missingValues.push("initiateLoginEndpoint");
|
|
900
921
|
}
|
|
901
|
-
if (!config.simpleAuthEndpoint) {
|
|
902
|
-
missingValues.push("simpleAuthEndpoint");
|
|
903
|
-
}
|
|
904
922
|
if (!config.clientId) {
|
|
905
923
|
missingValues.push("clientId");
|
|
906
924
|
}
|
|
@@ -908,111 +926,20 @@ class TeamsUserCredential {
|
|
|
908
926
|
internalLogger.error(errorMsg);
|
|
909
927
|
throw new ErrorWithCode(errorMsg, ErrorCode.InvalidConfiguration);
|
|
910
928
|
}
|
|
911
|
-
|
|
912
|
-
* Get axios instance with sso token bearer header
|
|
913
|
-
* @returns AxiosInstance
|
|
914
|
-
*/
|
|
915
|
-
async getAxiosInstance() {
|
|
916
|
-
const ssoToken = await this.getSSOToken();
|
|
917
|
-
const axiosInstance = axios.create({
|
|
918
|
-
baseURL: this.config.simpleAuthEndpoint,
|
|
919
|
-
});
|
|
920
|
-
axiosInstance.interceptors.request.use((config) => {
|
|
921
|
-
config.headers.Authorization = "Bearer " + ssoToken.token;
|
|
922
|
-
return config;
|
|
923
|
-
});
|
|
924
|
-
return axiosInstance;
|
|
925
|
-
}
|
|
926
|
-
/**
|
|
927
|
-
* Set access token to cache
|
|
928
|
-
* @param key
|
|
929
|
-
* @param token
|
|
930
|
-
*/
|
|
931
|
-
setTokenCache(key, token) {
|
|
932
|
-
Cache.set(key, JSON.stringify(token));
|
|
933
|
-
}
|
|
934
|
-
/**
|
|
935
|
-
* Get access token from cache.
|
|
936
|
-
* If there is no cache or cannot be parsed, then it will return null
|
|
937
|
-
* @param key
|
|
938
|
-
* @returns Access token or null
|
|
939
|
-
*/
|
|
940
|
-
getTokenCache(key) {
|
|
941
|
-
const value = Cache.get(key);
|
|
942
|
-
if (value === null) {
|
|
943
|
-
return null;
|
|
944
|
-
}
|
|
945
|
-
const accessToken = this.validateAndParseJson(value);
|
|
946
|
-
return accessToken;
|
|
947
|
-
}
|
|
948
|
-
/**
|
|
949
|
-
* Parses passed value as JSON access token, if value is not a valid json string JSON.parse() will throw an error.
|
|
950
|
-
* @param jsonValue
|
|
951
|
-
*/
|
|
952
|
-
validateAndParseJson(jsonValue) {
|
|
929
|
+
setSessionStorage(sessonStorageValues) {
|
|
953
930
|
try {
|
|
954
|
-
const
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
* of the parsed value is necessary in order to be certain that the string represents a valid JSON object.
|
|
959
|
-
*
|
|
960
|
-
*/
|
|
961
|
-
return parsedJson && typeof parsedJson === "object" ? parsedJson : null;
|
|
931
|
+
const sessionStorageKeys = Object.keys(sessonStorageValues);
|
|
932
|
+
sessionStorageKeys.forEach((key) => {
|
|
933
|
+
sessionStorage.setItem(key, sessonStorageValues[key]);
|
|
934
|
+
});
|
|
962
935
|
}
|
|
963
936
|
catch (error) {
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
* @param scopesStr
|
|
970
|
-
* @returns Access token cache key, a key example: accessToken-userId-clientId-tenantId-scopes
|
|
971
|
-
*/
|
|
972
|
-
async getAccessTokenCacheKey(scopesStr) {
|
|
973
|
-
const ssoToken = await this.getSSOToken();
|
|
974
|
-
const ssoTokenObj = parseJwt(ssoToken.token);
|
|
975
|
-
const clientId = this.config.clientId;
|
|
976
|
-
const userObjectId = ssoTokenObj.oid;
|
|
977
|
-
const tenantId = ssoTokenObj.tid;
|
|
978
|
-
const key = [accessTokenCacheKeyPrefix, userObjectId, clientId, tenantId, scopesStr]
|
|
979
|
-
.join(separator)
|
|
980
|
-
.replace(/" "/g, "_");
|
|
981
|
-
return key;
|
|
982
|
-
}
|
|
983
|
-
/**
|
|
984
|
-
* Check whether the token is about to expire (within 5 minutes)
|
|
985
|
-
* @returns Boolean value indicate whether the token is about to expire
|
|
986
|
-
*/
|
|
987
|
-
isAccessTokenNearExpired(token) {
|
|
988
|
-
const expireDate = new Date(token.expiresOnTimestamp);
|
|
989
|
-
if (expireDate.getTime() - Date.now() > tokenRefreshTimeSpanInMillisecond) {
|
|
990
|
-
return false;
|
|
937
|
+
// Values in result.sessionStorage can not be set into session storage.
|
|
938
|
+
// Throw error since this may block user.
|
|
939
|
+
const errorMessage = `Failed to set values in session storage. Error: ${error.message}`;
|
|
940
|
+
internalLogger.error(errorMessage);
|
|
941
|
+
throw new ErrorWithCode(errorMessage, ErrorCode.InternalError);
|
|
991
942
|
}
|
|
992
|
-
return true;
|
|
993
|
-
}
|
|
994
|
-
generateAuthServerError(err) {
|
|
995
|
-
var _a, _b;
|
|
996
|
-
let errorMessage = err.message;
|
|
997
|
-
if ((_b = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.type) {
|
|
998
|
-
errorMessage = err.response.data.detail;
|
|
999
|
-
if (err.response.data.type === "AadUiRequiredException") {
|
|
1000
|
-
const fullErrorMsg = "Failed to get access token from authentication server, please login first: " +
|
|
1001
|
-
errorMessage;
|
|
1002
|
-
internalLogger.warn(fullErrorMsg);
|
|
1003
|
-
return new ErrorWithCode(fullErrorMsg, ErrorCode.UiRequiredError);
|
|
1004
|
-
}
|
|
1005
|
-
else {
|
|
1006
|
-
const fullErrorMsg = "Failed to get access token from authentication server: " + errorMessage;
|
|
1007
|
-
internalLogger.error(fullErrorMsg);
|
|
1008
|
-
return new ErrorWithCode(fullErrorMsg, ErrorCode.ServiceError);
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
const fullErrorMsg = "Failed to get access token with error: " + errorMessage;
|
|
1012
|
-
return new ErrorWithCode(fullErrorMsg, ErrorCode.InternalError);
|
|
1013
|
-
}
|
|
1014
|
-
sleep(ms) {
|
|
1015
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1016
943
|
}
|
|
1017
944
|
}
|
|
1018
945
|
|
|
@@ -1155,7 +1082,7 @@ class DefaultTediousConnectionConfiguration {
|
|
|
1155
1082
|
* Only works in in server side.
|
|
1156
1083
|
* @beta
|
|
1157
1084
|
*/
|
|
1158
|
-
async getConfig() {
|
|
1085
|
+
async getConfig(databaseName) {
|
|
1159
1086
|
throw new ErrorWithCode(formatString(ErrorMessage.BrowserRuntimeNotSupported, "DefaultTediousConnectionConfiguration"), ErrorCode.RuntimeNotSupported);
|
|
1160
1087
|
}
|
|
1161
1088
|
}
|