@microsoft/teamsfx 2.2.0-alpha.034f24ebd.0 → 2.2.0-alpha.c0126420d.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 +170 -36
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -41,13 +41,27 @@ TeamsFx SDK is built to be used in browser and NodeJS environment. Common scenar
|
|
|
41
41
|
- Azure Function
|
|
42
42
|
- Teams bot
|
|
43
43
|
|
|
44
|
-
### Create and authenticate a service
|
|
44
|
+
### Create and authenticate a service using `createMicrosoftGraphClientWithCredential` or `createMicrosoftGraphClient`
|
|
45
|
+
|
|
46
|
+
> [!NOTE] `createMicrosoftGraphClient` function has been deprecated. It is recommended that you to use `createMicrosoftGraphClientWithCredential` instead, for better coding experience.
|
|
45
47
|
|
|
46
48
|
To create a graph client object to access the Microsoft Graph API, you will need the credential to do authentication. The SDK provides APIs to configure for developers. Please choose the proper identity type and follow below steps:
|
|
47
49
|
|
|
48
50
|
#### Invoke Graph API on behalf of Teams User (User Identity)
|
|
49
51
|
|
|
50
|
-
Use the snippet below:
|
|
52
|
+
Use the snippet below (Recommended):
|
|
53
|
+
```ts
|
|
54
|
+
const authConfig: TeamsUserCredentialAuthConfig = {
|
|
55
|
+
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
56
|
+
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const teamsUserCredential = new TeamsUserCredential(authConfig);
|
|
60
|
+
const graphClient = createMicrosoftGraphClientWithCredential(teamsUserCredential, ["User. Read"]);
|
|
61
|
+
const profile = await graphClient.api("/me").get();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
or use `createMicrosoftGraphClient` as below (Deprecated):
|
|
51
65
|
|
|
52
66
|
```ts
|
|
53
67
|
// Equivalent to:
|
|
@@ -63,7 +77,22 @@ const profile = await graphClient.api("/me").get(); // Get the profile of curren
|
|
|
63
77
|
#### Invoke Graph API without user (Application Identity)
|
|
64
78
|
|
|
65
79
|
It doesn't require the interaction with Teams user. You can call Microsoft Graph as application identity.
|
|
66
|
-
|
|
80
|
+
|
|
81
|
+
Use the snippet below (Recommended):
|
|
82
|
+
```ts
|
|
83
|
+
const appAuthConfig: AppCredentialAuthConfig = {
|
|
84
|
+
authorityHost: process.env.M365_AUTHORITY_HOST,
|
|
85
|
+
clientId: process.env.M365_CLIENT_ID,
|
|
86
|
+
tenantId: process.env.M365_TENANT_ID,
|
|
87
|
+
clientSecret: process.env.M365_CLIENT_SECRET,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const appCredential = new AppCredential(appAuthConfig);
|
|
91
|
+
const graphClient = createMicrosoftGraphClientWithCredential(appCredential);
|
|
92
|
+
const profile = await graphClient.api("/users/{object_id_of_another_people}").get();
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
or use `createMicrosoftGraphClient` as below (Deprecated):
|
|
67
96
|
|
|
68
97
|
```ts
|
|
69
98
|
// Equivalent to:
|
|
@@ -80,6 +109,8 @@ const profile = await graphClient.api("/users/{object_id_of_another_people}").ge
|
|
|
80
109
|
|
|
81
110
|
### TeamsFx class
|
|
82
111
|
|
|
112
|
+
> [!NOTE] `TeamsFx` class has been deprecated. It is recommended that you to use different credentials (`TeamsUserCredential`, `AppCredential`, `OnBehalfOfUserCredential`) instead, for better coding experience.
|
|
113
|
+
|
|
83
114
|
`TeamsFx` class instance reads all TeamsFx settings from environment variables by default. You can also set customized configuration values to override the default values. Please check [Override configuration](#override-configuration) for details.
|
|
84
115
|
|
|
85
116
|
When creating a TeamsFx instance, you also need to specify the identity type. There are 2 identity types:
|
|
@@ -114,19 +145,54 @@ Here's the corresponding scenarios that each credential class targets.
|
|
|
114
145
|
|
|
115
146
|
`TeamsUserCredential` represents Teams current user's identity. Using this credential will request user consent at the first time. It leverages the Teams SSO and On-Behalf-Of flow to do token exchange. SDK uses this credential when developer choose "User" identity in browser environment.
|
|
116
147
|
|
|
117
|
-
|
|
148
|
+
The following code is an an example to create TeamsUserCredential:
|
|
149
|
+
```ts
|
|
150
|
+
const authConfig: TeamsUserCredentialAuthConfig = {
|
|
151
|
+
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
152
|
+
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const credential = new TeamsUserCredential(authConfig);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Required configurations are initiateLoginEndpoint and clientId which can be found inside type TeamsUserCredentialAuthConfig.
|
|
118
159
|
|
|
119
160
|
#### User Identity in NodeJS environment
|
|
120
161
|
|
|
121
162
|
`OnBehalfOfUserCredential` uses On-Behalf-Of flow and need Teams ssoToken. It's designed to be used in Azure Function or Bot scenarios. SDK uses this credential when developer choose "User" identity in NodeJS environment.
|
|
122
163
|
|
|
123
|
-
|
|
164
|
+
The following code is an example to create OnBehalfOfUserCredential:
|
|
165
|
+
```ts
|
|
166
|
+
const oboAuthConfig: OnBehalfOfCredentialAuthConfig = {
|
|
167
|
+
authorityHost: process.env.M365_AUTHORITY_HOST,
|
|
168
|
+
clientId: process.env.M365_CLIENT_ID,
|
|
169
|
+
tenantId: process.env.M365_TENANT_ID,
|
|
170
|
+
clientSecret: process.env.M365_CLIENT_SECRET,
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const oboCredential = new OnBehalfOfUserCredential(ssoToken, oboAuthConfig);
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Required configurations are authorityHost, tenantId, clientId, clientSecret, or certificateContent which can be found inside type OnBehalfOfCredentialAuthConfig.
|
|
124
177
|
|
|
125
178
|
#### Application Identity in NodeJS environment
|
|
126
179
|
|
|
127
180
|
`AppCredential` represents the application identity. It is usually used when user is not involved like time-triggered automation job. SDK uses this credential when developer choose "App" identity in NodeJS environment.
|
|
128
181
|
|
|
129
|
-
|
|
182
|
+
|
|
183
|
+
The following code is an example to create `AppCredential`:
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
const appAuthConfig: AppCredentialAuthConfig = {
|
|
187
|
+
authorityHost: process.env.M365_AUTHORITY_HOST,
|
|
188
|
+
clientId: process.env.M365_CLIENT_ID,
|
|
189
|
+
tenantId: process.env.M365_TENANT_ID,
|
|
190
|
+
clientSecret: process.env.M365_CLIENT_SECRET,
|
|
191
|
+
};
|
|
192
|
+
const appCredential = new AppCredential(appAuthConfig);
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Required configurations are authorityHost, tenantId, clientId, clientSecret, or certificateContent which can be found inside type AppCredentialAuthConfig.
|
|
130
196
|
|
|
131
197
|
### Bot SSO
|
|
132
198
|
|
|
@@ -134,7 +200,26 @@ Bot related classes are stored under [bot](src/bot) folder.
|
|
|
134
200
|
|
|
135
201
|
`TeamsBotSsoPrompt` has a good integration with Bot framework. It simplifies the authentication process when you develops bot application and want to leverage the Bot SSO.
|
|
136
202
|
|
|
137
|
-
|
|
203
|
+
The following code is an example to create `TeamsBotSsoPrompt`:
|
|
204
|
+
|
|
205
|
+
```ts
|
|
206
|
+
const TeamsBotSsoPromptId = "TEAMS_BOT_SSO_PROMPT";
|
|
207
|
+
|
|
208
|
+
const settings: TeamsBotSsoPromptSettings = {
|
|
209
|
+
scopes: ["User.Read"],
|
|
210
|
+
timeout: 900000,
|
|
211
|
+
endOnInvalidMessage: true,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const authConfig: OnBehalfOfCredentialAuthConfig = {
|
|
215
|
+
authorityHost: process.env.M365_AUTHORITY_HOST,
|
|
216
|
+
clientId: process.env.M365_CLIENT_ID,
|
|
217
|
+
tenantId: process.env.M365_TENANT_ID,
|
|
218
|
+
clientSecret: process.env.M365_CLIENT_SECRET,
|
|
219
|
+
};
|
|
220
|
+
const loginUrl = process.env.INITIATE_LOGIN_ENDPOINT;
|
|
221
|
+
const ssoPrompt = new TeamsBotSsoPrompt(authConfig, loginUrl, TeamsBotSsoPromptId, settings);
|
|
222
|
+
```
|
|
138
223
|
|
|
139
224
|
### Helper Function
|
|
140
225
|
|
|
@@ -142,7 +227,7 @@ TeamsFx SDK provides several helper functions to ease the configuration for thir
|
|
|
142
227
|
|
|
143
228
|
#### Microsoft Graph Service
|
|
144
229
|
|
|
145
|
-
`createMicrosoftGraphClient` and `MsGraphAuthProvider` help to create authenticated Graph instance.
|
|
230
|
+
`createMicrosoftGraphClientWithCredential`, `createMicrosoftGraphClient`(deprecated) and `MsGraphAuthProvider` help to create authenticated Graph instance.
|
|
146
231
|
|
|
147
232
|
#### SQL
|
|
148
233
|
|
|
@@ -161,8 +246,13 @@ For example, to filter out specific error, you could use the following check:
|
|
|
161
246
|
|
|
162
247
|
```ts
|
|
163
248
|
try {
|
|
164
|
-
const
|
|
165
|
-
|
|
249
|
+
const authConfig: TeamsUserCredentialAuthConfig = {
|
|
250
|
+
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
251
|
+
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const credential = new TeamsUserCredential(authConfig);
|
|
255
|
+
await credential.login("User.Read");
|
|
166
256
|
} catch (err: unknown) {
|
|
167
257
|
if (err instanceof ErrorWithCode && err.code !== ErrorCode.ConsentFailed) {
|
|
168
258
|
throw err;
|
|
@@ -177,8 +267,13 @@ And if credential instance is used in other library like Microsoft Graph, it's p
|
|
|
177
267
|
|
|
178
268
|
```ts
|
|
179
269
|
try {
|
|
180
|
-
const
|
|
181
|
-
|
|
270
|
+
const authConfig: TeamsUserCredentialAuthConfig = {
|
|
271
|
+
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
272
|
+
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
273
|
+
};
|
|
274
|
+
|
|
275
|
+
const credential = new TeamsUserCredential(authConfig);
|
|
276
|
+
const graphClient = createMicrosoftGraphClientWithCredential(credential, ["User.Read"]); // Initializes MS Graph SDK using our MsGraphAuthProvider
|
|
182
277
|
const profile = await graphClient.api("/me").get();
|
|
183
278
|
} catch (err: unknown) {
|
|
184
279
|
// ErrorWithCode is handled by Graph client
|
|
@@ -202,12 +297,29 @@ The following sections provide several code snippets covering some of the most c
|
|
|
202
297
|
|
|
203
298
|
### Use Graph API in tab app
|
|
204
299
|
|
|
205
|
-
Use `
|
|
300
|
+
Use `createMicrosoftGraphClientWithCredential`.
|
|
206
301
|
|
|
207
302
|
```ts
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
303
|
+
const authConfig: TeamsUserCredentialAuthConfig = {
|
|
304
|
+
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
305
|
+
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
const teamsUserCredential = new TeamsUserCredential(authConfig);
|
|
309
|
+
|
|
310
|
+
// Put login code in a call-to-action callback function to avoid browser blocking automatically showing up pop-ups.
|
|
311
|
+
await teamsUserCredential.login(["User.Read"]); // Login with scope
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
const graphClient = createMicrosoftGraphClientWithCredential(teamsUserCredential, ["User. Read"]); // Initializes MS Graph SDK using our MsGraphAuthProvider
|
|
315
|
+
const profile = await graphClient.api("/me").get();
|
|
316
|
+
} catch (err: unknown) {
|
|
317
|
+
// ErrorWithCode is handled by Graph client
|
|
318
|
+
if (err instanceof GraphError && err.code?.includes(ErrorCode.UiRequiredError)) {
|
|
319
|
+
// Need to show login button to ask for user consent.
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
211
323
|
```
|
|
212
324
|
|
|
213
325
|
### Call Azure Function in tab app
|
|
@@ -215,15 +327,21 @@ const profile = await graphClient.api("/me").get();
|
|
|
215
327
|
Use `axios` library to make HTTP request to Azure Function.
|
|
216
328
|
|
|
217
329
|
```ts
|
|
218
|
-
|
|
219
|
-
const
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
const response = await
|
|
330
|
+
async function callFunction() {
|
|
331
|
+
const authConfig: TeamsUserCredentialAuthConfig = {
|
|
332
|
+
clientId: process.env.REACT_APP_CLIENT_ID,
|
|
333
|
+
initiateLoginEndpoint: process.env.REACT_APP_START_LOGIN_PAGE_URL,
|
|
334
|
+
};
|
|
335
|
+
const teamsUserCredential = new TeamsUserCredential(authConfig);
|
|
336
|
+
const accessToken = await teamsUserCredential.getToken(""); // Get SSO token
|
|
337
|
+
const endpoint = "https://YOUR_API_ENDPOINT";
|
|
338
|
+
const response = await axios.default.get(endpoint + "/api/" + functionName, {
|
|
339
|
+
headers: {
|
|
340
|
+
authorization: "Bearer " + accessToken.token,
|
|
341
|
+
},
|
|
342
|
+
});
|
|
343
|
+
return response.data;
|
|
344
|
+
}
|
|
227
345
|
```
|
|
228
346
|
|
|
229
347
|
### Access SQL database in Azure Function
|
|
@@ -256,10 +374,14 @@ connection.on("connect", (error) => {
|
|
|
256
374
|
### Use certificate-based authentication in Azure Function
|
|
257
375
|
|
|
258
376
|
```ts
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
377
|
+
const appAuthConfig: AppCredentialAuthConfig = {
|
|
378
|
+
authorityHost: process.env.M365_AUTHORITY_HOST,
|
|
379
|
+
clientId: process.env.M365_CLIENT_ID,
|
|
380
|
+
tenantId: process.env.M365_TENANT_ID,
|
|
381
|
+
certificateContent: 'PEM-encoded key certificate',
|
|
382
|
+
};
|
|
383
|
+
const appCredential = new AppCredential(appAuthConfig);
|
|
384
|
+
const token = appCredential.getToken();
|
|
263
385
|
```
|
|
264
386
|
|
|
265
387
|
### Use Graph API in Bot application
|
|
@@ -269,18 +391,30 @@ Add `TeamsBotSsoPrompt` to dialog set.
|
|
|
269
391
|
```ts
|
|
270
392
|
const { ConversationState, MemoryStorage } = require("botbuilder");
|
|
271
393
|
const { DialogSet, WaterfallDialog } = require("botbuilder-dialogs");
|
|
272
|
-
const { TeamsBotSsoPrompt } = require("@microsoft/teamsfx");
|
|
394
|
+
const { TeamsBotSsoPrompt, OnBehalfOfCredentialAuthConfig, TeamsBotSsoPromptSettings } = require("@microsoft/teamsfx");
|
|
273
395
|
|
|
274
396
|
const convoState = new ConversationState(new MemoryStorage());
|
|
275
397
|
const dialogState = convoState.createProperty("dialogState");
|
|
276
398
|
const dialogs = new DialogSet(dialogState);
|
|
277
399
|
|
|
278
|
-
const
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
400
|
+
const TeamsBotSsoPromptId = "TEAMS_BOT_SSO_PROMPT";
|
|
401
|
+
|
|
402
|
+
const settings: TeamsBotSsoPromptSettings = {
|
|
403
|
+
scopes: ["User.Read"],
|
|
404
|
+
timeout: 900000,
|
|
405
|
+
endOnInvalidMessage: true,
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
const authConfig: OnBehalfOfCredentialAuthConfig = {
|
|
409
|
+
authorityHost: process.env.M365_AUTHORITY_HOST,
|
|
410
|
+
clientId: process.env.M365_CLIENT_ID,
|
|
411
|
+
tenantId: process.env.M365_TENANT_ID,
|
|
412
|
+
clientSecret: process.env.M365_CLIENT_SECRET,
|
|
413
|
+
};
|
|
414
|
+
const loginUrl = process.env.INITIATE_LOGIN_ENDPOINT;
|
|
415
|
+
const ssoPrompt = new TeamsBotSsoPrompt(authConfig, loginUrl, TeamsBotSsoPromptId, settings);
|
|
416
|
+
|
|
417
|
+
dialogs.add(ssoPrompt);
|
|
284
418
|
|
|
285
419
|
dialogs.add(
|
|
286
420
|
new WaterfallDialog("taskNeedingLogin", [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@microsoft/teamsfx",
|
|
3
|
-
"version": "2.2.0-alpha.
|
|
3
|
+
"version": "2.2.0-alpha.c0126420d.0",
|
|
4
4
|
"description": "Microsoft Teams Framework for Node.js and browser.",
|
|
5
5
|
"main": "dist/index.node.cjs.js",
|
|
6
6
|
"browser": "dist/index.esm2017.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@azure/identity": "^2.0.1",
|
|
50
50
|
"@azure/msal-browser": "^2.21.0",
|
|
51
51
|
"@azure/msal-node": "~1.1.0",
|
|
52
|
-
"@microsoft/adaptivecards-tools": "1.2.2-alpha.
|
|
52
|
+
"@microsoft/adaptivecards-tools": "1.2.2-alpha.c0126420d.0",
|
|
53
53
|
"@microsoft/microsoft-graph-client": "^3.0.1",
|
|
54
54
|
"axios": "^0.27.2",
|
|
55
55
|
"botbuilder": ">=4.18.0 <5.0.0",
|
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
"webpack": "^5.62.1",
|
|
130
130
|
"yargs": "^17.2.1"
|
|
131
131
|
},
|
|
132
|
-
"gitHead": "
|
|
132
|
+
"gitHead": "22dcfada5eb6237da632834613314d92e1b0d3ba",
|
|
133
133
|
"publishConfig": {
|
|
134
134
|
"access": "public"
|
|
135
135
|
},
|