@microsoft/teamsfx 0.7.0-beta.01d6a9fb3.0 → 0.7.0-beta.1

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 CHANGED
@@ -205,14 +205,13 @@ Use `axios` library to make HTTP request to Azure Function.
205
205
 
206
206
  ```ts
207
207
  const teamsfx = new TeamsFx();
208
- const token = teamsfx.getCredential().getToken(""); // Get SSO token for the user
208
+ const credential = teamsfx.getCredential();
209
+ // Create an API client that uses SSO token to authenticate requests
210
+ const apiClient = createApiClient(
211
+ teamsfx.getConfig("apiEndpoint"),
212
+ new BearerTokenAuthProvider(async ()=> (await credential.getToken(""))!.token));
209
213
  // Call API hosted in Azure Functions on behalf of user
210
- const apiEndpoint = teamsfx.getConfig("apiEndpoint");
211
- const response = await axios.default.get(apiEndpoint + "api/httptrigger1", {
212
- headers: {
213
- authorization: "Bearer " + token,
214
- },
215
- });
214
+ const response = await apiClient.get("/api/" + functionName);
216
215
  ```
217
216
 
218
217
  ### Access SQL database in Azure Function
@@ -287,6 +286,27 @@ dialogs.add(
287
286
  );
288
287
  ```
289
288
 
289
+ ### Create API client to call existing API in Bot / Azure Function
290
+
291
+ ```ts
292
+ const teamsfx = new TeamsFx();
293
+
294
+ // Create an API Key auth provider. Following auth providers are also available:
295
+ // BearerTokenAuthProvider, BasicAuthProvider, CertificateAuthProvider
296
+ const authProvider = new ApiKeyProvider("your_api_key_name",
297
+ teamsfx.getConfig("YOUR_API_KEY_VALUE"), // This reads the value of YOUR_API_KEY_VALUE environment variable
298
+ ApiKeyLocation.Header);
299
+
300
+ // Create an API client using above auth provider
301
+ // You can also implement AuthProvider interface and use it here
302
+ const apiClient = createApiClient(
303
+ teamsfx.getConfig("YOUR_API_ENDPOINT"), // This reads YOUR_API_ENDPOINT environment variable
304
+ authProvider);
305
+
306
+ // Send a GET request to "relative_api_path"
307
+ const response = await apiClient.get("relative_api_path");
308
+ ```
309
+
290
310
  ## Advanced Customization
291
311
 
292
312
  ### Configure log
@@ -1,5 +1,5 @@
1
1
  import jwt_decode from 'jwt-decode';
2
- import * as microsoftTeams from '@microsoft/teams-js';
2
+ import { app, authentication } from '@microsoft/teams-js';
3
3
  import { PublicClientApplication } from '@azure/msal-browser';
4
4
  import { Client } from '@microsoft/microsoft-graph-client';
5
5
  import axios from 'axios';
@@ -548,51 +548,48 @@ class TeamsUserCredential {
548
548
  if (!this.initialized) {
549
549
  await this.init();
550
550
  }
551
- return new Promise((resolve, reject) => {
552
- microsoftTeams.initialize(() => {
553
- microsoftTeams.authentication.authenticate({
554
- url: `${this.config.initiateLoginEndpoint}?clientId=${this.config.clientId}&scope=${encodeURI(scopesStr)}&loginHint=${this.loginHint}`,
555
- width: loginPageWidth,
556
- height: loginPageHeight,
557
- successCallback: async (result) => {
558
- if (!result) {
559
- const errorMsg = "Get empty authentication result from MSAL";
560
- internalLogger.error(errorMsg);
561
- reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
562
- return;
563
- }
564
- let resultJson = {};
565
- try {
566
- resultJson = JSON.parse(result);
567
- }
568
- catch (error) {
569
- // If can not parse result as Json, will throw error.
570
- const failedToParseResult = "Failed to parse response to Json.";
571
- internalLogger.error(failedToParseResult);
572
- reject(new ErrorWithCode(failedToParseResult, ErrorCode.InvalidResponse));
573
- }
574
- // If code exists in result, user may using previous auth-start and auth-end page.
575
- if (resultJson.code) {
576
- const helpLink = "https://aka.ms/teamsfx-auth-code-flow";
577
- const usingPreviousAuthPage = "Found auth code in response. Auth code is not support for current version of SDK. " +
578
- `Please refer to the help link for how to fix the issue: ${helpLink}.`;
579
- internalLogger.error(usingPreviousAuthPage);
580
- reject(new ErrorWithCode(usingPreviousAuthPage, ErrorCode.InvalidResponse));
581
- }
582
- // If sessionStorage exists in result, set the values in current session storage.
583
- if (resultJson.sessionStorage) {
584
- this.setSessionStorage(resultJson.sessionStorage);
585
- }
586
- resolve();
587
- },
588
- failureCallback: (reason) => {
589
- const errorMsg = `Consent failed for the scope ${scopesStr} with error: ${reason}`;
590
- internalLogger.error(errorMsg);
591
- reject(new ErrorWithCode(errorMsg, ErrorCode.ConsentFailed));
592
- },
593
- });
594
- });
595
- });
551
+ await app.initialize();
552
+ let result;
553
+ try {
554
+ const params = {
555
+ url: `${this.config.initiateLoginEndpoint}?clientId=${this.config.clientId}&scope=${encodeURI(scopesStr)}&loginHint=${this.loginHint}`,
556
+ width: loginPageWidth,
557
+ height: loginPageHeight,
558
+ };
559
+ result = await authentication.authenticate(params);
560
+ if (!result) {
561
+ const errorMsg = "Get empty authentication result from MSAL";
562
+ internalLogger.error(errorMsg);
563
+ throw new ErrorWithCode(errorMsg, ErrorCode.InternalError);
564
+ }
565
+ }
566
+ catch (err) {
567
+ const errorMsg = `Consent failed for the scope ${scopesStr} with error: ${err.message}`;
568
+ internalLogger.error(errorMsg);
569
+ throw new ErrorWithCode(errorMsg, ErrorCode.ConsentFailed);
570
+ }
571
+ let resultJson = {};
572
+ try {
573
+ resultJson = typeof result == "string" ? JSON.parse(result) : result;
574
+ }
575
+ catch (error) {
576
+ // If can not parse result as Json, will throw error.
577
+ const failedToParseResult = "Failed to parse response to Json.";
578
+ internalLogger.error(failedToParseResult);
579
+ throw new ErrorWithCode(failedToParseResult, ErrorCode.InvalidResponse);
580
+ }
581
+ // If code exists in result, user may using previous auth-start and auth-end page.
582
+ if (resultJson.code) {
583
+ const helpLink = "https://aka.ms/teamsfx-auth-code-flow";
584
+ const usingPreviousAuthPage = "Found auth code in response. Auth code is not support for current version of SDK. " +
585
+ `Please refer to the help link for how to fix the issue: ${helpLink}.`;
586
+ internalLogger.error(usingPreviousAuthPage);
587
+ throw new ErrorWithCode(usingPreviousAuthPage, ErrorCode.InvalidResponse);
588
+ }
589
+ // If sessionStorage exists in result, set the values in current session storage.
590
+ if (resultJson.sessionStorage) {
591
+ this.setSessionStorage(resultJson.sessionStorage);
592
+ }
596
593
  }
597
594
  /**
598
595
  * Get access token from credential.
@@ -725,54 +722,41 @@ class TeamsUserCredential {
725
722
  * It will try to get SSO token from memory first, if SSO token doesn't exist or about to expired, then it will using teams SDK to get SSO token
726
723
  * @returns SSO token
727
724
  */
728
- getSSOToken() {
729
- return new Promise((resolve, reject) => {
730
- if (this.ssoToken) {
731
- if (this.ssoToken.expiresOnTimestamp - Date.now() > tokenRefreshTimeSpanInMillisecond) {
732
- internalLogger.verbose("Get SSO token from memory cache");
733
- resolve(this.ssoToken);
734
- return;
735
- }
725
+ async getSSOToken() {
726
+ if (this.ssoToken) {
727
+ if (this.ssoToken.expiresOnTimestamp - Date.now() > tokenRefreshTimeSpanInMillisecond) {
728
+ internalLogger.verbose("Get SSO token from memory cache");
729
+ return this.ssoToken;
736
730
  }
737
- if (this.checkInTeams()) {
738
- microsoftTeams.initialize(() => {
739
- microsoftTeams.authentication.getAuthToken({
740
- successCallback: (token) => {
741
- if (!token) {
742
- const errorMsg = "Get empty SSO token from Teams";
743
- internalLogger.error(errorMsg);
744
- reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
745
- return;
746
- }
747
- const tokenObject = parseJwt(token);
748
- if (tokenObject.ver !== "1.0" && tokenObject.ver !== "2.0") {
749
- const errorMsg = "SSO token is not valid with an unknown version: " + tokenObject.ver;
750
- internalLogger.error(errorMsg);
751
- reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
752
- return;
753
- }
754
- const ssoToken = {
755
- token,
756
- expiresOnTimestamp: tokenObject.exp * 1000,
757
- };
758
- this.ssoToken = ssoToken;
759
- resolve(ssoToken);
760
- },
761
- failureCallback: (errMessage) => {
762
- const errorMsg = "Get SSO token failed with error: " + errMessage;
763
- internalLogger.error(errorMsg);
764
- reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
765
- },
766
- resources: [],
767
- });
768
- });
769
- }
770
- else {
771
- const errorMsg = "Initialize teams sdk failed due to not running inside Teams";
772
- internalLogger.error(errorMsg);
773
- reject(new ErrorWithCode(errorMsg, ErrorCode.InternalError));
774
- }
775
- });
731
+ }
732
+ const params = {};
733
+ let token;
734
+ try {
735
+ await app.initialize();
736
+ token = await authentication.getAuthToken(params);
737
+ }
738
+ catch (err) {
739
+ const errorMsg = "Get SSO token failed with error: " + err.message;
740
+ internalLogger.error(errorMsg);
741
+ throw new ErrorWithCode(errorMsg, ErrorCode.InternalError);
742
+ }
743
+ if (!token) {
744
+ const errorMsg = "Get empty SSO token from Teams";
745
+ internalLogger.error(errorMsg);
746
+ throw new ErrorWithCode(errorMsg, ErrorCode.InternalError);
747
+ }
748
+ const tokenObject = parseJwt(token);
749
+ if (tokenObject.ver !== "1.0" && tokenObject.ver !== "2.0") {
750
+ const errorMsg = "SSO token is not valid with an unknown version: " + tokenObject.ver;
751
+ internalLogger.error(errorMsg);
752
+ throw new ErrorWithCode(errorMsg, ErrorCode.InternalError);
753
+ }
754
+ const ssoToken = {
755
+ token,
756
+ expiresOnTimestamp: tokenObject.exp * 1000,
757
+ };
758
+ this.ssoToken = ssoToken;
759
+ return ssoToken;
776
760
  }
777
761
  /**
778
762
  * Load and validate authentication configuration
@@ -1492,7 +1476,7 @@ function sendAdaptiveCard(target, card) {
1492
1476
  */
1493
1477
  class Channel {
1494
1478
  /**
1495
- * Constuctor.
1479
+ * Constructor.
1496
1480
  *
1497
1481
  * @remarks
1498
1482
  * Only work on server side.
@@ -1557,7 +1541,7 @@ class Channel {
1557
1541
  */
1558
1542
  class Member {
1559
1543
  /**
1560
- * Constuctor.
1544
+ * Constructor.
1561
1545
  *
1562
1546
  * @remarks
1563
1547
  * Only work on server side.