Service | Microsoft Docs article | Related commit history on GitHub | Change details |
---|---|---|---|
platform | Meeting Apps Apis | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/apps-in-teams-meetings/meeting-apps-apis.md | The following table provides a list of APIs available across the Microsoft Teams To identify and retrieve contextual information for your tab content, see [get context for your Teams tab](../tabs/how-to/access-teams-context.md#get-context-by-using-the-microsoft-teams-javascript-library). `meetingId` is used by a tab running in the meeting context and is added for the response payload. +### Examples ++The following are the TeamsJS v2 responses for Get user context API based on meeting type, user type, and call type: ++* Meeting type ++ # [Channel meeting](#tab/channel-meeting) ++ The following is a JSON payload response for a channel meeting for in-tenant users: ++ ```json + { + "app": { + "locale": "en-us", + "sessionId": "ff47ec00-e6a7-4dc1-a6ae-f44110f50c94", + "theme": "default", + "iconPositionVertical": 0, + "osLocaleInfo": { + "platform": "windows", + "regionalFormat": "en-in", + "shortDate": "dd-MM-yyyy", + "longDate": "dd MMMM yyyy", + "shortTime": "HH:mm", + "longTime": "HH:mm:ss" + }, + "parentMessageId": "1678109354022", + "userClickTime": 1678109521159, + "userFileOpenPreference": "inline", + "host": { + "name": "Teams", + "clientType": "desktop", + "sessionId": "c3c3c0a0-f7a1-b070-6b89-c8cd1f380042", + "ringId": "ring1" + }, + "appLaunchId": "7346ae66-5cac-47f9-8a0d-1228dac474cb" + }, + "page": { + "id": "Test", + "frameContext": "sidePanel", + "subPageId": "", + "isFullScreen": false, + "isMultiWindow": true, + "sourceOrigin": "" + }, + "user": { + "id": "57efa5f3-273c-47e2-a871-4879e5d849cf", + "displayName": "", + "isCallingAllowed": undefined, + "isPSTNCallingAllowed": undefined, + "licenseType": "Unknown", + "loginHint": "v-prkamble@microsoft.com", + "userPrincipalName": "v-prkamble@microsoft.com", + "tenant": { + "id": "72f988bf-86f1-41af-91ab-2d7cd011db47", + "teamsSku": "enterprise" + } + }, + "channel": { + "id": "19:49683807ffce4318ad6d6d7a24dbde45@thread.tacv2", + "displayName": undefined, + "relativeUrl": undefined, + "membershipType": undefined, + "defaultOneNoteSectionId": undefined, + "ownerGroupId": undefined, + "ownerTenantId": undefined + }, + "chat": { + "id": "19:49683807ffce4318ad6d6d7a24dbde45@thread.tacv2" + }, + "meeting": { + "id": "MCMxOTo0OTY4MzgwN2ZmY2U0MzE4YWQ2ZDZkN2EyNGRiZGU0NUB0aHJlYWQudGFjdjIjMTY3ODEwOTM1NDAyMg==" + }, + "sharepoint": undefined, + "team": { + "internalId": "19:b34aeec3f8e54240a5c283e86bfc4878@thread.tacv2", + "displayName": undefined, + "type": undefined, + "groupId": undefined, + "templateId": undefined, + "isArchived": undefined, + "userRole": 1 + }, + "sharePointSite": { + "teamSiteUrl": "", + "teamSiteDomain": "microsoft.sharepoint.com", + "teamSitePath": "", + "teamSiteId": "", + "mySitePath": undefined, + "mySiteDomain": undefined + } + } + ``` ++ # [Scheduled meeting](#tab/scheduled-meeting) ++ The following is a JSON payload response for a scheduled meeting for in-tenant users: ++ ```json + { + "app": { + "locale": "en-us", + "sessionId": "e746c935-0991-47b8-b7f4-16db7646771f", + "theme": "default", + "iconPositionVertical": 22.998046875, + "osLocaleInfo": null, + "parentMessageId": "", + "userClickTime": 1678023107126, + "userFileOpenPreference": "inline", + "host": { + "name": "Teams", + "clientType": "web", + "sessionId": "5f2a15f6-75bd-2612-c0ff-2e1085dd165a", + "ringId": "general" + }, + "appLaunchId": "e07b6f2c-dc0f-4de2-9b1f-44dba2ea733c" + }, + "page": { + "id": "Test", + "frameContext": "content", + "subPageId": "", + "isFullScreen": false, + "isMultiWindow": false, + "sourceOrigin": NULL + }, + "user": { + "id": "e652dd92-dd63-4fcc-b5b2-2005681e8e9f", + "displayName": null, + "isCallingAllowed": null, + "isPSTNCallingAllowed": null, + "licenseType": "Unknown", + "loginHint": "admin@M365x94626565.onmicrosoft.com", + "userPrincipalName": "admin@M365x94626565.onmicrosoft.com", + "tenant": { + "id": "aa923623-ae61-49ee-b401-81f414b6ad5a", + "teamsSku": "enterprise" + } + }, + "channel": null, + "chat": { + "id": "19:meeting_YmU5NWM3NGEtZjMyMi00ZDg4LTk4OGUtMjUzMGJkZjRhMDhm@thread.v2" + }, + "meeting": { + "id": "MCMxOTptZWV0aW5nX1ltVTVOV00zTkdFdFpqTXlNaTAwWkRnNExUazRPR1V0TWpVek1HSmtaalJoTURobUB0aHJlYWQudjIjMA==" + }, + "sharepoint": null, + "team": null, + "sharePointSite": { + "teamSiteUrl": "", + "teamSiteDomain": "m365x94626565.sharepoint.com", + "teamSitePath": "", + "teamSiteId": null, + "mySitePath": "/personal/admin_m365x94626565_onmicrosoft_com", + "mySiteDomain": "m365x94626565-my.sharepoint.com" + } + } ++ ``` ++ # [Instant meeting](#tab/instant-meeting) ++ The following is a JSON payload response for a Instant meeting (Meet now) for in-tenant users: ++ ```json + { + "app": { + "locale": "en-us", + "sessionId": "4b2b69ef-6030-4379-a07b-02a64ff3bd37", + "theme": "default", + "iconPositionVertical": 23, + "parentMessageId": "", + "userClickTime": 1681216672213, + "userFileOpenPreference": "inline", + "host": { + "name": "Teams", + "clientType": "web", + "sessionId": "a384245b-c4ee-0c76-377b-7394bd040532", + "ringId": "ring3_6" + }, + "appLaunchId": "f7e97fbd-0b2e-477f-9599-91a5155418d5" + }, + "page": { + "id": "Test", + "frameContext": "content", + "subPageId": "", + "isFullScreen": false, + "isMultiWindow": false, + "sourceOrigin": null + }, + "user": { + "id": "4ebcc4d0-291b-4154-a85f-a89cd77aefa8", + "licenseType": "Unknown", + "loginHint": "admin@M365x654992.onmicrosoft.com", + "userPrincipalName": "admin@M365x654992.onmicrosoft.com", + "tenant": { + "id": "36a708ef-700d-4d60-9de0-0a5f7b7693df", + "teamsSku": "unknown" + } + }, + "chat": { + "id": "19:meeting_OWRiMjg0N2YtNDc1Ni00YWEyLWE4YjgtODkwZTliMzczYzg1@thread.v2" + }, + "meeting": { + "id": "MCMxOTptZWV0aW5nX09XUmlNamcwTjJZdE5EYzFOaTAwWVdFeUxXRTRZamd0T0Rrd1pUbGlNemN6WXpnMUB0aHJlYWQudjIjMA==" + }, + "sharePointSite": { + "teamSiteUrl": "", + "teamSiteDomain": "m365x654992.sharepoint.com", + "teamSitePath": "", + "mySitePath": "/personal/admin_m365x654992_onmicrosoft_com", + "mySiteDomain": "m365x654992-my.sharepoint.com" + } + } + ``` ++ ++* User type ++ # [Guest user](#tab/guest-user) ++ The following is a JSON payload response in a scheduled private meeting for a guest user : ++ ```json + { + "app": { + "locale": "en-us", + "sessionId": "268beeb4-a52d-4ba8-b1c8-8b9f0b9b3492", + "theme": "default", + "iconPositionVertical": 23, + "osLocaleInfo": { + "platform": "windows", + "regionalFormat": "en-in", + "longDate": "dd MMMM yyyy", + "shortDate": "dd-MM-yyyy", + "longTime": "HH:mm:ss", + "shortTime": "HH:mm" + }, + "parentMessageId": "", + "userClickTime": 1678023265131, + "userFileOpenPreference": "inline", + "host": { + "name": "Teams", + "clientType": "desktop", + "sessionId": "967c980b-1e41-a2cd-eac0-a4bff8f73ce7", + "ringId": "ring1" + }, + "appLaunchId": "c35c4496-f28c-4107-8e6c-2dba09fb881a" + }, + "page": { + "id": "Test", + "frameContext": "content", + "subPageId": "", + "isFullScreen": false, + "isMultiWindow": false, + "sourceOrigin": NULL + }, + "user": { + "id": "57efa5f3-273c-47e2-a871-4879e5d849cf", + "displayName": undefined, + "isCallingAllowed": undefined, + "isPSTNCallingAllowed": undefined, + "licenseType": "Unknown", + "loginHint": "v-prkamble@microsoft.com", + "userPrincipalName": "v-prkamble@microsoft.com", + "tenant": { + "id": "72f988bf-86f1-41af-91ab-2d7cd011db47", + "teamsSku": "enterprise" + } + }, + "channel": undefined, + "chat": { + "id": "19:meeting_YmU5NWM3NGEtZjMyMi00ZDg4LTk4OGUtMjUzMGJkZjRhMDhm@thread.v2" + }, + "meeting": { + "id": "MCMxOTptZWV0aW5nX1ltVTVOV00zTkdFdFpqTXlNaTAwWkRnNExUazRPR1V0TWpVek1HSmtaalJoTURobUB0aHJlYWQudjIjMA==" + }, + "sharepoint": undefined, + "team": undefined, + "sharePointSite": { + "teamSiteUrl": "", + "teamSiteDomain": "microsoft.sharepoint.com", + "teamSitePath": "", + "teamSiteId": undefined, + "mySitePath": "/personal/v-prkamble_microsoft_com", + "mySiteDomain": "microsoft-my.sharepoint.com" + } + } + ``` ++ # [Anonymous user](#tab/anonymous-user) ++ The following is a JSON payload response in a scheduled private meeting for an anonymous user: ++ ```json + { +     "app": { +         "locale": "en-us", +         "sessionId": "a57af773-73b1-480c-a525-0c9487a51792", +         "theme": "dark", +         "parentMessageId": "", +         "userClickTime": 1678369341888, +         "host": { +             "name": "Teams", +             "clientType": "web", +             "sessionId": "", +             "ringId": "general" +         } +     }, +     "page": { +         "frameContext": "meetingStage", +         "subPageId": "", +         "isMultiWindow": false, +         "sourceOrigin": "" +     }, +     "user": { +         "id": "", +         "licenseType": "Anonymous", +         "loginHint": "", +         "userPrincipalName": "" +     }, +     "chat": { +         "id": "19:meeting_NTZmNTI3ODgtOWZkOS00NjgzLWJhNTMtMDhlNjE5ZjAwYWYx@thread.v2" +     }, +     "meeting": { +         "id": "MCMxOTptZWV0aW5nX05UWm1OVEkzT0RndE9XWmtPUzAwTmpnekxXSmhOVE10TURobE5qRTVaakF3WVdZeEB0aHJlYWQudjIjMA==" +     } + } + ``` ++ # [External user](#tab/external-user) ++ The following is a JSON payload response in a scheduled private meeting for an external user: ++ ```json + { + "app": { + "locale": "en-us", + "sessionId": "fe4d7f01-e049-4238-8c5a-3c6bcf4517cd", + "theme": "default", + "iconPositionVertical": 0, + "osLocaleInfo": { + "platform": "windows", + "regionalFormat": "en-us", + "shortDate": "M/d/yyyy", + "longDate": "dddd, MMMM d, yyyy", + "shortTime": "h:mm tt", + "longTime": "h:mm:ss tt" + }, + "parentMessageId": "", + "userClickTime": 0, + "userFileOpenPreference": "inline", + "host": { + "name": "Teams", + "clientType": "desktop", + "sessionId": "d6d8d834-b13c-95bb-96bd-3bed74fdad4c", + "ringId": "ring1" + }, + "appLaunchId": "4ce26ee3-a6b6-4dad-9484-3b218d5603be" + }, + "page": { + "id": "Test", + "frameContext": "sidePanel", + "subPageId": "", + "isFullScreen": false, + "isMultiWindow": true, + "sourceOrigin": "" + }, + "user": { + "id": "aeee11b1-7838-4b4a-8064-12ce5b01258f", + "displayName": "", + "licenseType": "Unknown", + "loginHint": "v-hrajandira@microsoft.com", + "userPrincipalName": "v-hrajandira@microsoft.com", + "tenant": { + "id": "72f988bf-86f1-41af-91ab-2d7cd011db47", + "teamsSku": "enterprise" + } + }, + "chat": { + "id": "19:meeting_Mzg5ZmQwYzItY2U3NS00MDE4LThkZjQtMzNjNWZiMzM5MzNi@thread.v2" + }, + "meeting": { + "id": "MCMxOTptZWV0aW5nX016ZzVabVF3WXpJdFkyVTNOUzAwTURFNExUaGtaalF0TXpOak5XWmlNek01TXpOaUB0aHJlYWQudjIjMA==" + }, + "sharePointSite": { + "teamSiteUrl": "", + "teamSiteDomain": "microsoft.sharepoint.com", + "teamSitePath": "", + "teamSiteId": "" + } + } ++ ``` ++ ++* Call type ++ # [One-on-One call](#tab/one-on-one-call) ++ The following is a JSON payload response for a one-on-one call for an in-tenant user: ++ ```json + { + "app": { + "locale": "en-us", + "sessionId": "1b3dc47e-f6ae-4fe2-8ed6-844a505f3186", + "theme": "dark", + "iconPositionVertical": null, + "osLocaleInfo": { + "platform": "windows", + "regionalFormat": "en-in", + "shortDate": "dd-MM-yyyy", + "longDate": "dd MMMM yyyy", + "shortTime": "HH:mm", + "longTime": "HH:mm:ss" + }, + "parentMessageId": "", + "userClickTime": 1678088052473, + "userFileOpenPreference": undefined, + "host": { + "name": "Teams", + "clientType": "desktop", + "sessionId": "", + "ringId": "general" + }, + "appLaunchId": undefined + }, + "page": { + "id": "Test", + "frameContext": "sidePanel", + "subPageId": "", + "isFullScreen": undefined, + "isMultiWindow": true, + "sourceOrigin": "" + }, + "user": { + "id": "e652dd92-dd63-4fcc-b5b2-2005681e8e9f", + "displayName": undefined, + "isCallingAllowed": undefined, + "isPSTNCallingAllowed": undefined, + "licenseType": "Unknown", + "loginHint": "admin@M365x94626565.onmicrosoft.com", + "userPrincipalName": "admin@M365x94626565.onmicrosoft.com", + "tenant": { + "id": "aa923623-ae61-49ee-b401-81f414b6ad5a", + "teamsSku": "unknown" + } + }, + "channel": undefined, + "chat": { + "id": "19:a74d8489-4455-4670-9581-7b38a8017c58_e652dd92-dd63-4fcc-b5b2-2005681e8e9f@unq.gbl.spaces" + }, + "meeting": { + "id": "MCMxOTphNzRkODQ4OS00NDU1LTQ2NzAtOTU4MS03YjM4YTgwMTdjNThfZTY1MmRkOTItZGQ2My00ZmNjLWI1YjItMjAwNTY4MWU4ZTlmQHVucS5nYmwuc3BhY2VzIzA=" + }, + "sharepoint": undefined, + "team": undefined, + "sharePointSite": { + "teamSiteUrl": undefined, + "teamSiteDomain": "m365x94626565.sharepoint.com", + "teamSitePath": undefined, + "teamSiteId": undefined, + "mySitePath": undefined, + "mySiteDomain": undefined + } + } ++ ``` ++ # [Group call](#tab/group-call) ++ The following is a JSON payload response for a group chat call for an in-tenant user: ++ ```json + { + "app": { + "locale": "en-us", + "sessionId": "cbc005c1-8c10-4dfb-a7c6-711353009cc3", + "theme": "dark", + "iconPositionVertical": undefined, + "osLocaleInfo": { + "platform": "windows", + "regionalFormat": "en-in", + "shortDate": "dd-MM-yyyy", + "longDate": "dd MMMM yyyy", + "shortTime": "HH:mm", + "longTime": "HH:mm:ss" + }, + "parentMessageId": "", + "userClickTime": 1678087909562, + "userFileOpenPreference": undefined, + "host": { + "name": "Teams", + "clientType": "desktop", + "sessionId": "", + "ringId": "general" + }, + "appLaunchId": undefined + }, + "page": { + "id": "Test", + "frameContext": "sidePanel", + "subPageId": "", + "isFullScreen": undefined, + "isMultiWindow": true, + "sourceOrigin": "" + }, + "user": { + "id": "e652dd92-dd63-4fcc-b5b2-2005681e8e9f", + "displayName": undefined, + "isCallingAllowed": undefined, + "isPSTNCallingAllowed": undefined, + "licenseType": "Unknown", + "loginHint": "admin@M365x94626565.onmicrosoft.com", + "userPrincipalName": "admin@M365x94626565.onmicrosoft.com", + "tenant": { + "id": "aa923623-ae61-49ee-b401-81f414b6ad5a", + "teamsSku": "unknown" + } + }, + "channel": undefined, + "chat": { + "id": "19:a91b5c5f7dbc4eb58e8592240db70299@thread.v2" + }, + "meeting": { + "id": "MCMxOTphOTFiNWM1ZjdkYmM0ZWI1OGU4NTkyMjQwZGI3MDI5OUB0aHJlYWQudjIjMA==" + }, + "sharepoint": undefined, + "team": undefined, + "sharePointSite": { + "teamSiteUrl": undefined, + "teamSiteDomain": "m365x94626565.sharepoint.com", + "teamSitePath": undefined, + "teamSiteId": undefined, + "mySitePath": undefined, + "mySiteDomain": undefined + } + } + + ``` ++ + ## Get participant API The `GetParticipant` API must have a bot registration and ID to generate auth tokens. For more information, see [bot registration and ID](/azure/bot-service/bot-service-quickstart-registration). |
platform | Channel And Group Conversations | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/conversations/channel-and-group-conversations.md | Title: Create conversation bots for channel or group chat -description: Learn how to create new conversation threads, work on mentions, and send message on install. Explore Teams file upload sample (.NET, JavaScript, Python). +description: Learn how to create new conversation threads, work on user and tag mentions, and send message on install. Explore Teams file upload sample (.NET, JavaScript, Python). ms.localizationpriority: medium def get_mentions(activity: Activity) -> List[Mention]: ### Add mentions to your messages -Your bot can mention other users in messages posted into channels. +There are two types of mentions: ++* [User mention](#user-mention) +* [Tag mention](#tag-mention) ++#### User mention ++Your bot can mention other users in messages posted in channels. The `Mention` object has two properties that you must set using the following: The Bot Framework SDK provides helper methods and objects to create mentions. The following code shows an example of adding mentions to your messages: # [C#](#tab/dotnet)+ * [SDK reference](/dotnet/api/microsoft.bot.schema.mention?view=botbuilder-dotnet-stable&preserve-view=true) * [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-conversation/csharp/Bots/TeamsConversationBot.cs#L300) The `text` field in the object in the `entities` array must match a portion of t ``` # [Python](#tab/python)+ * [SDK reference](/python/api/botbuilder-schema/botbuilder.schema.mention?view=botbuilder-py-latest&preserve-view=true) * [Sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/bot-conversation/python/bots/teams_conversation_bot.py#L94) async def _mention_activity(self, turn_context: TurnContext): Now you can send an introduction message when your bot is first installed or added to a group or team. +#### Tag mention ++Your bot can mention tags in text messages and Adaptive Cards posted in channels. When the bot @mentions the tag in a channel, the tag is highlighted and the people associated with the tag get notified. When a user hovers over the tag, a pop-up appears with the tag details. ++> [!NOTE] +> +> * Tag mentions are available only in [public developer preview](../../../resources/dev-preview/developer-preview-intro.md). +> * Tag mentions are supported in Teams desktop and web clients. However, it's not supported in Teams mobile client. +> * Tag mentions are supported in Government Community Cloud (GCC) and GCC-High tenants, and not supported in Department of Defense (DoD) tenant. ++##### Mention tags in a text message ++In the `mention.properties` object, add the property `'type': 'tag'`. If the property `'type': 'tag'` isn't added, the bot treats the mention as a user mention. ++Example: ++The `type:tag` is added as a `Properties` in ChannelAccount. ++[SDK reference](/dotnet/api/microsoft.bot.schema.channelaccount?view=botbuilder-dotnet-stable&branch=main&preserve-view=true) ++```csharp +ΓÇïvar mention = new ChannelAccount(tagId, "Test Tag"); +ΓÇïmention.Properties = JObject.Parse("{'type': 'tag'}"); +ΓÇïvar mentionObj = new Mention +ΓÇï{ +ΓÇï Mentioned = mention, +ΓÇï Text = "<at>Test Tag</at>" +ΓÇï}; ++ΓÇïvar replyActivity = MessageFactory.Text("Hello " + mentionObj.Text); +ΓÇïreplyActivity.Entities = new List<Microsoft.Bot.Schema.Entity> { mentionObj }; +ΓÇïawait turnContext.SendActivityAsync(replyActivity, cancellationToken); +``` ++##### Mention tags in an Adaptive Card ++In the Adaptive Card schema, under the `mentioned` object, add the `"type": "tag"` property. If the `"type": "tag"` property isn't added, the bot treats the mention as a user mention. ++You can get the list of the tags available in the channel using the [List teamworkTags](/graph/api/teamworktag-list?view=graph-rest-1.0&tabs=http&preserve-view=true) API. ++Example: ++```json +ΓÇï{ +ΓÇï "type": "mention", + ΓÇï"text": "<at>Test Tag</at>", +ΓÇï "mentioned": { + ΓÇï"id": "base64 encoded id" ,// tag graph 64 base ID +ΓÇï "name": "Test Tag", + ΓÇï"type": "tag" +ΓÇï } +ΓÇï} +``` ++###### Query Parameters ++|Name |Description | +||-| +|`type`| The type of mention. The supported type is `tag`.| +|`id`|The unique identifier for the tag. For more information, see [teamworkTag](/graph/api/resources/teamworktag?view=graph-rest-1.0&preserve-view=true).| ++###### Error code ++| Status code | Error code | Message values | Retry request | Developer action| +|-|--|--|-|-| +| 400 | **Code**: `Bad Request` | ΓÇïMentioned tag with ID {id string} doesn't exist in current team<br/>ΓÇïTag can only be mentioned in channel<br/>Invalid mentioned tag because no tag exists in the team| No | Reevaluate request payload for errors. Check returned error message for details. | +| 502 | **Code**: `Bad Gateway` | Invalid team group ID<br/> ΓÇïMalformed tenant ID for the tag<br/> ΓÇïMention ID can't be resolved | No |Retry manually.| ++##### Throttling limits ++Any request can be evaluated against multiple limits, depending on the scope, the window type (short and long), number of tags per message, and other factors. The first limit to be reached triggers throttling behavior. ++Ensure that you don't exceed the throttling limits to avoid failed message delivery. For example, a bot can send only two messages with tags mention in a five-second window and each message can have only up to 10 tags. ++The following table lists the throttling limits for tag mentions in a bot: ++| ΓÇïScope | ΓÇïWindow Type | Number of tags per message | ΓÇïTime windows (sec) | ΓÇïMaximum number of messages per time window | +|||--|-|-| +|ΓÇïPer bot per thread | ΓÇïShort | 10 | 5 | 2 | +| | ΓÇïLong | 10 | 60 | 5 | +|ΓÇïAll bots per thread | ΓÇïShort | 10 | 5 | 4 | +| | Long | 10 | 60 | 5 | ++##### Limitations ++* Tag mentions are supported only in bot to client message flow with text and Adaptive Card. +* Tag mentions aren't supported in shared and private channels. +* Tag mentions aren't supported in connectors. +* Tag mentions don't support the invoke flow in a bot. + ## Send a message on installation When your bot is first added to the group or team, an introduction message must be sent. The message must provide a brief description of the bot's features and how to use them. You must subscribe to the `conversationUpdate` event with the `teamMemberAdded` eventType. The event is sent when any new team member is added. Check if the new member added is the bot. For more information, see [sending a welcome message to a new team member](~/bots/how-to/conversations/send-proactive-messages.md). |
platform | Conversation Messages | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/conversations/conversation-messages.md | The following code shows an example of sending a simple Adaptive Card: } ``` -#### Form completion feedback --You can build form completion feedback using an Adaptive Card. Form completion message appears in Adaptive Cards while sending a response to the bot. The message can be of two types, error or success: --* **Error**: When a response sent to the bot is unsuccessful, **Something went wrong, Try again** message appears. -- :::image type="content" source="../../../assets/images/Cards/error-message.png" alt-text="Error message"border="true"::: --* **Success**: When a response sent to the bot is successful, **Your response was sent to the app** message appears. -- :::image type="content" source="../../../assets/images/Cards/success.PNG" alt-text="Success message"border="true"::: -- You can select **Close** or switch chat to dismiss the message. -- If you don't want to display the success message, set the attribute `hide` to `true` in the `msTeams` `feedback` property. Following is an example: -- ```json - "content": { - "type": "AdaptiveCard", - "title": "Card with hidden footer messages", - "version": "1.0", - "actions": [ - { - "type": "Action.Submit", - "title": "Submit", - "msTeams": { - "feedback": { - "hide": true - } - } - } - ] - } - ``` --For more information on cards and cards in bots, see [cards documentation](~/task-modules-and-cards/what-are-cards.md). - ## Add notifications to your message There are two ways to send a notification from your application: |
platform | Send Proactive Messages | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/bots/how-to/conversations/send-proactive-messages.md | The following table provides a simple code sample that incorporates basic conver * [Build your first bot app using JavaScript](../../../sbs-gs-bot.yml) * [Build notification bot with JavaScript to send a proactive message](../../../sbs-gs-notificationbot.yml) * [TurnContext](/javascript/api/botbuilder-core/turncontext?view=botbuilder-ts-latest"&preserve-view=true")+* [Implement custom storage for bot](/azure/bot-service/bot-builder-custom-storage) |
platform | Shared Channels | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/concepts/build-and-test/shared-channels.md | Microsoft Teams Connect shared channels allow members of a channel to collaborat Teams Connect shared channels facilitate secure collaboration seamlessly. Allow external users outside of your organization to collaborate with internal users in Teams without changing their user context. Enhance user experience unlike using guest accounts, for example, the members must sign out of Teams and sign in again using a guest account. Teams applications extend the powerful collaboration space. ## Enable your app for shared channels |
platform | Include Saas Offer | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/concepts/deploy-and-publish/appsource/prepare/include-saas-offer.md | If you unlink a SaaS offer included in your Teams store listing, you must republ * [Monetize your app](monetize-overview.md) * [Maintaining and supporting your published app](../post-publish/overview.md) * [Validation guidelines for apps linked to SaaS offer](teams-store-validation-guidelines.md#apps-linked-to-saas-offer)+* [Microsoft commercial marketplace](/partner-center/marketplace/overview) |
platform | Publish | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/concepts/deploy-and-publish/appsource/publish.md | If your app is production ready, you can begin the process of getting it listed > [!TIP] > Following the pre-submission steps closely can increase the possibility that Microsoft approves your app for publishing. - :::column span=""::: -- :::column-end::: - :::column span="3"::: - :::image type="content" source="../../../assets/images/submission/teams-app-store-publish-process.png" alt-text="Teams app store publishing process" lightbox="../../../assets/images/submission/teams-app-store-publish-process.png"::: - :::column-end::: - :::column span=""::: -- :::column-end::: 1. [Review the Teams store validation guidelines](~/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines.md) to ensure your app meets Teams app and store standards. If your app is production ready, you can begin the process of getting it listed 1. Review the [store validation guidelines](prepare/teams-store-validation-guidelines.md) again to ensure that your app is in alignment with the store requirements. Review helps reduce the number of issues observed in your app and so, the time taken to approve your app. - 1. Test and re-test your app: + 1. Test and retest your app: 1. Validate your app package using the Teams [Developer Portal](https://dev.teams.microsoft.com/home) to identify and fix any package errors. If your app is production ready, you can begin the process of getting it listed * **During design phase** - Review the [store validation guidelines specific to apps published with linked SaaS offers](~/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines.md#apps-linked-to-saas-offer) early in your app's life cycle (design phase) to ensure that you build your app in alignment with the store requirements and [Microsoft Commercial Marketplace policies applicable to Teams apps linked to SaaS offers](/legal/marketplace/certification-policies#11405-teams-app-linked-to-software-as-a-service-saas-offers). If you build your app in line with these guidelines, then it prevents any rework due to non-adherence to store policies. + Review the [store validation guidelines specific to apps published with linked SaaS offers](~/concepts/deploy-and-publish/appsource/prepare/teams-store-validation-guidelines.md#apps-linked-to-saas-offer) early in your app's life cycle (design phase) to ensure that you build your app in alignment with the store requirements and [Microsoft Commercial Marketplace policies applicable to Teams apps linked to SaaS offers](/legal/marketplace/certification-policies#11405-teams-app-linked-to-software-as-a-service-saas-offers). If you build your app in line with these guidelines, then it prevents any rework due to nonadherence to store policies. * **Prior to app submission** |
platform | Design Teams App Icon Store Appbar | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/concepts/design/design-teams-app-icon-store-appbar.md | When submitting your app package, include two PNG versions of the app icon, a co ### Balanced layout -The icons are intended to create a uniform layout. These guidelines helps you create your app icon for submission. +The icons are intended to create a uniform layout. These guidelines help you create your app icon for submission. :::image type="content" source="../../assets/images/design-guidelines/app-icon-balanced-layout.png" alt-text="Example shows the uniform layout for app icons."::: Refer this list for content areas where your icon shows in the product, dependin :::column span=""::: :::image type="content" source="../../assets/images/design-guidelines/safe-area-do.png" alt-text="Example shows a logo within the safe area."::: -#### Do: Follow the recommendation for safe area (96 x 96) +#### Do: Follow the recommendation for safe area (120 x 120) -It is recommended that if you have a logo, keep it within the 96 x 96 safe area inside of the 192 x 192 PNG format icon. +It's recommended that if you have a logo, keep it within the 120 x 120 safe area inside of the 192 x 192 PNG format icon. :::column-end::: :::column span=""::: It is recommended that if you have a logo, keep it within the 96 x 96 safe area #### DonΓÇÖt: Make the icon bigger than the safe area -Here is an example of a logo inside of the PNG format icon that is not within the safe area. It creates uneven padding (negative space) around the icon. +Here's an example of a logo inside of the PNG format icon that isn't within the safe area. It creates uneven padding (negative space) around the icon. :::column-end::: :::row-end::: Border is added automatically. In this case just upload your PNG format without #### DonΓÇÖt: Add a border -Borders are added dynamically. If you include a border in your PNG format, it'll result in unwanted duplication on white backgrounds. +Borders are added dynamically. If you include a border in your PNG format, it results in unwanted duplication on white backgrounds. :::column-end::: :::row-end::: If you have a long app name, try to abbreviate so that itΓÇÖs easier to read whe #### DonΓÇÖt: Include multiple words in app icon -Avoid using multiple words on the icon. It is impossible to read the text when the icon is at smaller sizes for example 32 x 32 or 36 x 36. +Avoid using multiple words on the icon. It's impossible to read the text when the icon is at smaller sizes, for example, 32 x 32 or 36 x 36. :::column-end::: :::row-end::: |
platform | Native Device Permissions | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/concepts/device-capabilities/native-device-permissions.md | Title: Request device permissions for your Microsoft Teams app description: How to update your app manifest in order to request access to native features that require user consent, such as scan QR, barcode, image, audio, and video capabilities +ms.localizationpriority: high Last updated 03/21/2023 |
platform | Developer Preview Intro | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/resources/dev-preview/developer-preview-intro.md | Last updated 01/31/2023 # Public developer preview for Teams >[!NOTE]->Features included in preview may not be complete, and may undergo changes before becoming available in the public release. They are provided for testing and exploration purposes only. They should not be used in production applications. +>Features included in preview may not be complete and may undergo changes before becoming available in the public release. They are provided for testing and exploration purposes only. They should not be used in production applications. Developer Preview is a public program for developers, which provides early access to unreleased features in Microsoft Teams. This allows you to explore and test upcoming features for potential inclusion in your Teams app. We also welcome [feedback](~/feedback.md) on any feature in developer preview. Developer preview is enabled per Microsoft Teams client, so you don't need to worry about affecting your entire organization. ## Developer preview app manifest -Many features enabled in developer preview require alterations to your app manifest JSON file. To do so, you need to use the [developer preview manifest schema](~/resources/schem) to make these changes, nor you can use it to upload your app for testing. To upload your app you need to select the `More apps` icon on the app bar, then select the `Upload a custom app link`. Using this method you can only upload a zipped version of your app package. +Many features enabled in developer preview require alterations to your app manifest JSON file. To do so, you need to use the [developer preview manifest schema](~/resources/schem) to make these changes, nor you can use it to upload your app for testing. To upload your app, you need to select the `More apps` icon on the app bar, then select the `Upload a custom app link`. Using this method, you can only upload a zipped version of your app package. You may find it useful to use Developer Portal for Teams to create the non-developer preview portions of your app package, then export that package and manually edit the `manifest.json` file to add the developer preview features you wish to use. Once you've added developer preview features to the `manifest.json` file, you can't reimport the package into Developer Portal for Teams. ## Enable developer preview -Developer preview is enabled on a per-client basis, but the option to turn on developer preview is controlled at the organization level. To enable the option to turn on developer preview for an individual, you must ensure that they have the ability to upload custom apps. See [setting up your tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md) for additional information. +Developer preview is enabled on a per-client basis, but the option to turn on developer preview is controlled at the organization level. To enable the option to turn on developer preview for an individual, you must ensure that they have the ability to upload custom apps. For more information, see [setting up your tenant](~/concepts/build-and-test/prepare-your-o365-tenant.md). Using an app that contains developer preview features may cause clients that haven't enabled developer preview to behave unexpectedly. If you don't see an entry for developer preview, the most likely reason is your organization isn't configured for app uploading. To enable the public developer preview on a mobile client: 1. Select **About**. 1. Turn on the **Developer preview** toggle. +> [!NOTE] +> If you [enable custom Teams apps and turn on custom app uploading](../../concepts/build-and-test/prepare-your-o365-tenant.md#enable-custom-teams-apps-and-turn-on-custom-app-uploading) doesn't enable developer preview features in Microsoft Teams [set the update policy](/MicrosoftTeams/public-preview-doc-updates#set-the-update-policy). + ## Disable developer preview -Use the same menu item under About → Developer preview, and select it to turn it off. +Use the same menu item under About → Developer preview and select it to turn it off. ## See also |
platform | Auth Flow Tab | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/authentication/auth-flow-tab.md | This section uses Azure AD as an example of a third-party OAuth provider for ena > [!NOTE] > Before showing a **Login** button to the user and calling the `authentication.authenticate` API in response to selecting the button, you must wait for the TeamsJS initialization to complete. You can chain a `.then()` handler or `await` for the `app.initialize()` function to complete. - 1. The user interacts with the content on the tab configuration or content page, commonly a **Sign in** or **Log in** button. 2. The tab constructs the URL for its auth start page. Optionally, it uses information from URL placeholders or calls `app.getContext()` TeamsJS method to streamline the authentication experience for the user. For example, when authenticating with Azure AD, if the `login_hint` parameter is set to the user's email address, the user doesn't have to sign in if they've done so recently. This is because Azure AD uses the user's cached credentials. The pop-up window is shown briefly and then disappears. |
platform | Tab Sso Graph Api | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/authentication/tab-sso-graph-api.md | description: Configure additional permissions and scopes, get access token with ms.localizationpriority: high keywords: teams authentication tabs Microsoft Azure Active Directory (Azure AD) Graph API Delegated permission access token scope Previously updated : 04/06/2023 Last updated : 07/14/2023 # Extend tab app with Microsoft Graph permissions and scopes -You can extend your tab app by using Microsoft Graph to allow users additional permissions, such as to view app user profile, to read mail, and more. Your app must ask for specific permission scopes to obtain the access tokens on app user's consent. +You can extend your tab app by using Microsoft Graph to allow additional user permissions, such as to view app user profile, read mail, and more. Your app must ask for specific permission scopes to obtain the access tokens upon app user consent. -Graph scopes, such as `User.Read` or `Mail.Read`, lets you specify how your app accesses a Teams user's account. You need to specify your scopes in the authorization request. --In this section, you'll learn to: --- [Configure API permissions in Azure AD](#configure-api-permissions-in-azure-ad)-- [Configure authentication for different platforms](#configure-authentication-for-different-platforms)-- [Acquire access token for MS Graph](#acquire-access-token-for-ms-graph)+Graph scopes, such as `User.Read` or `Mail.Read`, indicate what your app can access from a Teams user account. You need to specify your scopes in the authorization request. This article walks you through the steps to configure Microsoft Graph permissions and scopes for your Teams tab app. ## Configure API permissions in Azure AD -You can configure additional Graph scopes in Azure AD for your app. These are delegated permissions, which are used by apps that require signed-in access. A signed-in app user or administrator must consent to them. Your tab app can consent on behalf of the signed-in user when it calls Microsoft Graph. +You can configure additional Graph scopes in Azure AD for your app. These are delegated permissions, which are used by apps that require signed-in access. A signed-in app user or administrator must initially consent to them. Thereafter, your tab app can consent on behalf of the signed-in user when it calls Microsoft Graph. ### To configure API permissions You can configure additional Graph scopes in Azure AD for your app. These are de :::image type="content" source="../../../assets/images/authentication/teams-sso-tabs/configured-permissions.png" alt-text="The screenshot shows an example of the API permissions, which are configured."::: - You've configured your app with Microsoft Graph permissions. + You've now configured your app with Microsoft Graph permissions. ## Configure authentication for different platforms -Depending on the platform or device where you want to target your app, additional configuration may be required such as redirect URIs, specific authentication settings, or details specific to the platform. +Depending on the platform or device where you want to target your app, additional configuration may be required, such as redirect URIs, specific authentication settings, or details specific to the platform. > [!NOTE] >-> - If your tab app hasn't been granted IT admin consent, app users have to provide consent the first time they use your app on a different platform. +> - If your tab app hasn't been granted IT admin consent, app users need to provide consent the first time they use your app on a different platform. > - Implicit grant isn't required if SSO is enabled on a tab app. You can configure authentication for multiple platforms as long as the URL is unique. You can configure authentication for multiple platforms as long as the URL is un The Configure Web page appears. > [!NOTE]- > The configurations will be different based on the platform you select. + > The configurations are different based on the platform you select. 1. Enter the configuration details for the platform. You can configure authentication for multiple platforms as long as the URL is un ## Acquire access token for MS Graph -You'll need to acquire access token for Microsoft Graph. You can do so by using Azure AD on-behalf-of (OBO) flow. --The current implementation for SSO grants consent for only user-level permissions that aren't usable for making Graph calls. To get the permissions (scopes) needed to make a Graph call, SSO apps must implement a custom web service to exchange the token received from the Teams JavaScript library for a token that includes the needed scopes. You can use Microsoft Authentication Library (MSAL) for fetching the token from the client side. --After you've configured Graph permissions in Azure AD: +You need to acquire an access token for Microsoft Graph. You can do so by using Azure AD on-behalf-of (OBO) flow. -1. [Get the token ID from Teams client](#get-the-token-id-from-teams-client) +The current implementation for single sign-on (SSO) is limited to user-level permissions, which aren't usable for making Graph calls. To get the permissions and scopes needed to make a Graph call, SSO apps must implement a custom web service to exchange the token received from the Teams JavaScript library for a token that includes the needed scopes. You can use Microsoft Authentication Library (MSAL) for fetching the token from the client side. -1. [Exchange the token ID with the server-side token](#exchange-the-token-id-with-the-server-side-token) +After you've configured Graph permissions in Azure AD, you'll need to get the token ID from the Teams client and then exchange it with the server-side token. ### Get the token ID from Teams client -The following is an example for calling token ID from Teams client: +The following is an example for getting the token ID from Teams client: ```csharp microsoftTeams.authentication.getAuthToken().then((result) => { microsoftTeams.authentication.getAuthToken().then((result) => { ### Exchange the token ID with the server-side token -The following is an example of OBO flow to fetch access token from the Teams client using MSAL: +The following is an example of OBO flow to fetch the access token from Teams client using MSAL: ### [C#](#tab/dotnet) IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create ### [Node.js](#tab/nodejs) -- [SDK reference](/javascript/api/@azure/msal-node/confidentialclientapplication?view=azure-node-latest#@azure-msal-node-confidentialclientapplication-acquiretokenonbehalfof&preserve-view=true)--- [sample code reference](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/tab-sso/nodejs/src/server/tabs.js#L51-L94)+[ConfidentiaClientApplication class](/javascript/api/@azure/msal-node/confidentialclientapplication?view=azure-node-latest#@azure-msal-node-confidentialclientapplication-acquiretokenonbehalfof&preserve-view=true) SDK reference | [sample code](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/tab-sso/nodejs/src/server/tabs.js#L51-L94) ```Node.js // Exchange client Id side token with server token IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create If you need to access Microsoft Graph data, configure your server-side code to: 1. Validate the access token. For more information, see [Validate the access token](tab-sso-code.md#validate-the-access-token).-1. Initiate the OAuth 2.0 OBO flow with a call to the Microsoft identity platform that includes the access token, some metadata about the user, and the credentials of the tab app (its app ID and client secret). The Microsoft identity platform will return a new access token that can be used to access Microsoft Graph. +1. Initiate the OAuth 2.0 OBO flow with a call to the Microsoft identity platform that includes the access token, some metadata about the user, and the credentials of the tab app (its app ID and client secret). The Microsoft identity platform returns a new access token that can be used to access Microsoft Graph. 1. Get data from Microsoft Graph by using the new token. 1. Use token cache serialization in MSAL.NET to cache the new access token for multiple, if necessary. > [!IMPORTANT] >-> - As a best practice for security, always use the [server-side code to make Microsoft Graph calls](/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#middle-tier-access-token-request) or other calls that require passing an access token. You must not return the OBO token to the client because it enables the client to make direct calls to Microsoft Graph. This helps protect the token from being intercepted or leaked. +> - As a best practice for security, always use [server-side code to make Microsoft Graph calls](/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow#middle-tier-access-token-request) or other calls that require passing an access token. This helps protect the token from being intercepted or leaked. DO NOT return the OBO token to the client because it would then enable the client to make direct calls to Microsoft Graph. > > - DonΓÇÖt use `notifySuccess` result to return the token information to the parent page. Use `localStorage` to save the token and pass the item key via `notifySuccess`. -## Known limitations +## Obtain consent ++Your app can obtain consent for Graph permissions globally from the tenant administrator, or individually per user. ++### From the tenant administrator -1. Tenant admin consent: A simple way of [consenting on behalf of an organization as a tenant admin](/azure/active-directory/manage-apps/consent-and-permissions-overview#admin-consent) is by getting [consent from admin](/azure/active-directory/manage-apps/grant-admin-consent). + A simple way of [consenting on behalf of an organization](/azure/active-directory/manage-apps/consent-and-permissions-overview#admin-consent) is by obtaining [admin consent](/azure/active-directory/manage-apps/grant-admin-consent). - You can ask for consent using the Auth API. Another approach for getting Graph scopes is to present a consent dialog using our existing [third party OAuth provider authentication approach](~/tabs/how-to/authentication/auth-tab-aad.md#navigate-to-the-authorization-page-from-your-pop-up-page). This approach involves popping up an Azure AD consent dialog box. +### From the user - <details> - <summary>To ask for additional consent using the Auth API, follow these steps:</summary> +When asking for additional user consent using the Microsoft Teams JavaScript client library (TeamsJS) [authentication](/javascript/api/@microsoft/teams-js/authentication) capability, keep in mind the following considerations: - 1. The token retrieved using `getAuthToken()` must be exchanged on the server-side using Azure AD [on-behalf-of flow](/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow) to get access to those other Graph APIs. Ensure you use the v2 Graph endpoint for this exchange. - 2. If the exchange fails, Azure AD returns an invalid grant exception. It usually responds with one of the two error messages, `invalid_grant` or `interaction_required`. - 3. When the exchange fails, you must ask for consent. Use the user interface (UI) to ask the app user to grant other consent. This UI must include a button that triggers an Azure AD consent dialog using [Silent authentication](~/concepts/authentication/auth-silent-aad.md). - 4. When asking for more consent from Azure AD, you must include `prompt=consent` in your [query-string-parameter](~/tabs/how-to/authentication/auth-silent-aad.md#get-the-user-context) to Azure AD, otherwise Azure AD wouldn't ask for other scopes. - - Instead of `?scope={scopes}`, use `?prompt=consent&scope={scopes}` - - Ensure that `{scopes}` includes all the scopes you're prompting the user for, for example, `Mail.Read` or `User.Read`. +> [!TIP] +> [Teams Personal Tab SSO Authentication](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/main/samples/tab-personal-sso-quickstart/js/src/components/Tab.js#L64-L101) sample provides code demonstrating following steps. - To handle incremental consent for tab app, see [incremental and dynamic user consent](/azure/active-directory/develop/v2-permissions-and-consent). - 5. After the app user has granted more permissions, retry the OBO flow to get access to these other APIs. - </details> +1. The token retrieved using `getAuthToken()` must be exchanged on the server-side using Azure AD [OBO flow](/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow) to get access to those other Graph APIs. Ensure that you use the Azure AD v2 endpoint for this exchange. +1. When you try to execute the token exchange for a user for the first time, if Azure AD refuses to exchange tokens it might be because the user hasn't consented to give your app permission to the user's data. In these cases, your exchange fails with either the `invalid_grant` or `interaction_required` error. Examples of *invalid_grant* errors include when consent is required or *auth_code*, assertion, or the refresh token is expired, revoked, malformed, or absent. Examples of *interaction_required* include when multi-factor authentication or corporate device enrollment is required. +1. If the exchange fails because of the `invalid_grant` or `interaction_required` errors, you must prompt the user for consent. Since user interaction can only happen from the client, your server needs to return an indication to your client app that consent is required. You can then use the user interface (UI) to ask the app user to grant other consent. The UI must include a button that triggers an [Azure AD consent dialog](../../../tabs/how-to/authentication/tab-sso-code.md#consent-dialog-for-getting-access-token). +1. To ask the user for consent for your app to access their data, you must include the `prompt=consent` property in your [query-string-parameter](/azure/active-directory/develop/v2-oauth2-implicit-grant-flow#send-the-sign-in-request) to Azure AD. + - Instead of `?scope={scopes}`, use `?prompt=consent&scope={scopes}` + - Ensure that the `{scopes}` property includes all the scopes you're prompting the user for. For example, `Mail.Read` or `User.Read`. -1. Race condition in fetching Graph access token via on-behalf-of (OBO) flow after consent: If your app calls Microsoft Graph, you might use the on-behalf-of (OBO) flow in your API to get a valid Graph token for that user. + To handle incremental consent for tab app, see [incremental and dynamic user consent](/azure/active-directory/develop/v2-permissions-and-consent). +1. After the app user has granted more permissions, retry the OBO flow to get access to additional Graph APIs. - If a user hasn't granted Azure AD application consent for these scopes, your OBO call will fail with `invalid_grant` or `interaction_required` error. This error informs you that you need to prompt the user for their consent. +## Race condition when making an OBO call after invalid grant exception - When the user has provided their consent and you try to make an OBO call immediately, sometimes there's a race condition between Azure AD propagating this consent and the OBO request taking place. This can lead to OBO call failing with the same `invalid_grant` or `interaction_required` errors. +If a user hasn't granted Azure AD application consent for these scopes, your OBO call fails with `invalid_grant` or `interaction_required` error. This error informs you that you need to prompt the user for their consent. - If your application is unaware of this behaviour, it might ask the user for consent multiple times. +When the user has provided their consent and you try to make an OBO call immediately, sometimes there's a race condition between Azure AD propagating this consent and the OBO request taking place. This can lead to OBO call failing with the same `invalid_grant` or `interaction_required` errors. - There's no workaround to this limitation. Azure AD recommends that you can build a meaningful wait-and-retry mechanism to overcome this issue. +If your application is unaware of this behavior, it might ask the user for consent multiple times. Best practice is to build a meaningful wait-and-retry mechanism to avoid this suboptimal user experience. - This wait-and-retry mechanism should keep track if a user has consented to the required scopes. If an API call that includes an OBO request fails with the above errors, but the user has already consented, avoid showing the consent prompt to the user. Instead, wait for some time before retrying the API call. Usually, Azure AD sends the consent within three to five seconds. In one of our [sample applications](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/8f266c33608d6d7b4cf89c81779ccf49e7664c1e/samples/bot-tab-conversations/csharp/Source/ConversationalTabs.Web/ClientApp/src/utils/UtilsFunctions.ts#LL8C1-L8C1), we retry up to three times with double the wait time between each retry, starting at a one second wait. +This wait-and-retry mechanism should keep track if a user has consented to the required scopes. If an API call that includes an OBO request fails with the above errors, but the user has already consented, avoid showing the consent prompt to the user. Instead, wait for some time before retrying the API call. Usually, Azure AD sends the consent within three to five seconds. In one of our [sample applications](https://github.com/OfficeDev/Microsoft-Teams-Samples/blob/8f266c33608d6d7b4cf89c81779ccf49e7664c1e/samples/bot-tab-conversations/csharp/Source/ConversationalTabs.Web/ClientApp/src/utils/UtilsFunctions.ts#LL8C1-L8C1), we retry up to three times with double the wait time between each retry, starting at a one second wait. - If after three to five attempts the OBO flow still fails, the user might not have consented to all the required scopes, and you may have to prompt them to consent again. +If after three to five attempts the OBO flow still fails, the user might not have consented to all the required scopes, and you may have to prompt them to consent again. - This approach helps reduce the possibility of user being prompted for consent more than once. +This approach helps reduce the possibility of user being prompted for consent more than once. ## Code sample |
platform | Build Adaptive Card Tabs | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/build-adaptive-card-tabs.md | Follow the [step-by-step](../../sbs-tab-with-adaptive-cards.yml) guide to build * [Tabs on mobile](../design/tabs-mobile.md) * [Cards](../../task-modules-and-cards/what-are-cards.md) * [Use task modules in tabs](../../task-modules-and-cards/task-modules/task-modules-tabs.md)-* [Form completion feedback](../../bots/how-to/conversations/conversation-messages.md#form-completion-feedback) +* [Form completion feedback](../../task-modules-and-cards/cards/cards-format.md#form-completion-feedback) |
platform | Developer Tools | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/tabs/how-to/developer-tools.md | Title: DevTools for Microsoft Teams tabs -description: In this module, learn how to get to the DevTools when using the Microsoft Teams Desktop Client and debugging +description: In this module, learn how to get to the DevTools when using the Microsoft Teams Desktop Client and debugging. ms.localizationpriority: medium Last updated 08/29/2022 When Teams is running in a browser, it's easy to access the browser's DevTools: While the web version and the desktop version of Teams are almost the same, there are some differences concerning authentication. Sometimes the only way to figure out what is going on is to use the DevTools. To use DevTools in the desktop client, you must: -1. Ensure you have enabled [developer preview](~/resources/dev-preview/developer-preview-intro.md). +1. Ensure you have enabled [Enable developer preview](../../resources/dev-preview/developer-preview-intro.md#enable-developer-preview). 1. Open up a tab so you have something to inspect with the DevTools. 1. Open the DevTools one of the following ways: * On Windows, you open DevTools via the Microsoft Teams icon in the desktop tray. |
platform | Sequential Workflows | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/task-modules-and-cards/cards/Universal-actions-for-adaptive-cards/Sequential-Workflows.md | var adaptiveCardResponse = JObject.FromObject(new * [Adaptive Card actions in Teams](~/task-modules-and-cards/cards/cards-actions.md#adaptive-cards-actions) * [How bots work](/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0&preserve-view=true) * [Work with Universal Actions for Adaptive Cards](Work-with-universal-actions-for-adaptive-cards.md)-* [Form completion feedback](~/bots/how-to/conversations/conversation-messages.md#form-completion-feedback) +* [Form completion feedback](../cards-format.md#form-completion-feedback) |
platform | Up To Date Views | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/task-modules-and-cards/cards/Universal-actions-for-adaptive-cards/Up-To-Date-Views.md | The following code provides an example of Adaptive Cards sent as response of `ad * [Cards and task modules](../../cards-and-task-modules.md) * [Work with Universal Actions for Adaptive Cards](Work-with-universal-actions-for-adaptive-cards.md) * [User Specific Views](User-Specific-Views.md)-* [Form completion feedback](~/bots/how-to/conversations/conversation-messages.md#form-completion-feedback)* +* [Form completion feedback](../cards-format.md#form-completion-feedback) |
platform | User Specific Views | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/task-modules-and-cards/cards/Universal-actions-for-adaptive-cards/User-Specific-Views.md | The following list provides card design guidelines for User Specific Views: * [Work with Universal Actions for Adaptive Cards](Work-with-Universal-Actions-for-Adaptive-Cards.md) * [Up to date cards](Up-To-Date-Views.md) * [Cards](../../what-are-cards.md)-* [Form completion feedback](../../../bots/how-to/conversations/conversation-messages.md#form-completion-feedback) +* [Form completion feedback](../cards-format.md#form-completion-feedback) |
platform | Work With Universal Actions For Adaptive Cards | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/task-modules-and-cards/cards/Universal-actions-for-adaptive-cards/Work-with-Universal-Actions-for-Adaptive-Cards.md | For more information, see [backward compatibility on Teams](/adaptive-cards/auth * [Basics of the Microsoft Bot Framework](/azure/bot-service/bot-builder-basics?view=azure-bot-service-4.0&preserve-view=true) * [Sequential Workflows](~/task-modules-and-cards/cards/universal-actions-for-adaptive-cards/sequential-workflows.md) * [Up to date cards](~/task-modules-and-cards/cards/universal-actions-for-adaptive-cards/up-to-date-views.md)-* [Form completion feedback](~/bots/how-to/conversations/conversation-messages.md#form-completion-feedback) +* [Form completion feedback](../cards-format.md#form-completion-feedback) |
platform | Cards Actions | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/task-modules-and-cards/cards/cards-actions.md | CardFactory.actions([ Adaptive Cards support four action types: -* [Action.OpenUrl](https://adaptivecards.io/explorer/Action.OpenUrl.html) -* [Action.Submit](https://adaptivecards.io/explorer/Action.Submit.html) -* [Action.ShowCard](https://adaptivecards.io/explorer/Action.ShowCard.html) -* [Action.Execute](/adaptive-cards/authoring-cards/universal-action-model#actionexecute) +* [Action.OpenUrl](https://adaptivecards.io/explorer/Action.OpenUrl.html): Open the specified url. +* [Action.Submit](https://adaptivecards.io/explorer/Action.Submit.html): Sends the result of the submit action to the bot. +* [Action.ShowCard](https://adaptivecards.io/explorer/Action.ShowCard.html): Invokes a dialog and renders the sub-card into that dialog. You only need to handle this if `ShowCardActionMode` is set to popup. +* [Action.ToggleVisibility](https://adaptivecards.io/explorer/Action.ToggleVisibility.html): Shows or hides one or more elements in the card. +* [Action.Execute](/adaptive-cards/authoring-cards/universal-action-model#actionexecute): Gathers the input fields, merges with optional data field, and sends an event to the client. -You can also modify the Adaptive Card `Action.Submit` payload to support existing Bot Framework actions using an `msteams` property in the `data` object of `Action.Submit`. The next section provides details on how to use existing Bot Framework actions with Adaptive Cards. +### Action.Submit ++`Action.Submit` type is used to gather the input, combine the `data` properties, and send an event to the bot. When a user selects the submit action, Teams sends a message activity to the bot, which includes the user's input in key-value pairs for all input fields and hidden data that is defined in the card payload. ++In the Adaptive Card schema, the `data` property for Action.Submit is either a `string` or an `object`. A submit action behaves differently for each data property: ++* `string`: A string submit action automatically sends a message from the user to the bot and is visible in the conversation history. +* `object`: An object submit action automatically sends an invisible message from the user to the bot that contains hidden data. An object submit action populates the activityΓÇÖs value property while the text property is empty. ++Action.Submit is equivalent to the Bot Framework actions. You can also modify the Adaptive Card `Action.Submit` payload to support existing Bot Framework actions using an `msteams` property in the `data` object of `Action.Submit`. When you define the `msteams` property under `data`, the `Action.Submit` behavior is defined by Teams client. If the `msteams` property isn't defined in the schema, `Action.Submit` works like a regular Bot Framework invoke action, where; the submit action triggers an invoke call to the bot and the bot receives the payload with all the input values defined in the input fields. > [!NOTE] > >* Adding `msteams` to data with a Bot Framework action doesn't work with an Adaptive Card task module.-> >* Primary or destructive `ActionStyle` isn't supported in Microsoft Teams. >* Your app has five seconds to respond to the invoke message. +#### Example ++The following is an example of a `Action.Submit` card payload: ++The payload consists of a text input field `"id": "text-1"` and hidden data payload `"hiddenKey": 123.45`. ++```json +{ + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "type": "AdaptiveCard", + "version": "1.5", + "fallbackText": "fallback text for sample 01", + "speak": "This is adaptive card sample 1", + "body": [ + { + "type": "Container", + "items": [ + { + "id": "text-1", + "type": "Input.Text" + } + ] + } + ], + "actions": [ + { + "type": "Action.Submit", + "data": { + "hiddenKey": 123.45 + } + } + ] +} +``` +++The following is an example of the incoming activity to a bot when user types something in the input field and selects **Submit**. The `value` attribute includes the user's input in the `text-1` property and a hidden data payload in the `hiddenKey` property: ++ ```json + +{ + "type": "message", + "timestamp": "2023-07-18T23:45:41.699Z", + "localTimestamp": "2023-07-18T16:45:41.699-07:00", + "id": "f:9eb18f56-2259-8fa4-7dfc-111ffff58e67", + "channelId": "msteams", + "serviceUrl": "https://smba.trafficmanager.net/amer/", + "from": { + "id": "29:1E0NZYNZFQOCUI8zM9NY_EhlCsWgNbLGTHUNdBVX2ob8SLjhltEhQMPi07Gr6MLScFeS8SrKH1WGvJSiVKThnyw", + "name": "Robin Liao", + "aadObjectId": "97b1ec61-45bf-453c-9059-6e8984e0cef4" + }, + "conversation": { + "conversationType": "personal", + "tenantId": "72f988bf-86f1-41af-91ab-2d7cd011db47", + "id": "a:1H-RowZ3FrIheyjTupPnoCC6JvOLB5pCWms1xwqvAJG97j61D18EuSennYZE6tyfbQrnfIN3uIcwpOx73mg10hHp_uoTMMQlXhXosIu_q7QVCaYiW6Ch3bPWAitUw4aSX" + }, + "recipient": { + "id": "28:159e1c0f-15ef-4597-a8c6-44ba1fd89b78", + "name": "Mushroom" + }, + "entities": [ + { + "locale": "en-US", + "country": "US", + "platform": "Web", + "timezone": "America/Los_Angeles", + "type": "clientInfo" + } + ], + "channelData": { + "tenant": { + "id": "72f988bf-86f1-41af-91ab-2d7cd011db47" + }, + "source": { + "name": "message" + }, + "legacy": { + "replyToId": "1:1XFuAl7wF96vl6iAQk9tqus0uFrB89uujGpld-Qm-XEw" + } + }, + "replyToId": "1689723936016", + "value": { + "hiddenKey": 123.45, + "text-1": "HELLO" + }, + "locale": "en-US", + "localTimezone": "America/Los_Angeles" +} + ``` ++The next section provides details on how to use existing Bot Framework actions with Adaptive Cards. + ### Adaptive Cards with messageBack action To include a `messageBack` action with an Adaptive Card include the following details in the `msteams` object: The following code shows an example of Adaptive Cards with `invoke` action with * [Types of cards](cards-reference.md) * [Use task modules from bots](~/task-modules-and-cards/task-modules/task-modules-bots.md) * [Adaptive Cards in bots](../../bots/how-to/conversations/conversation-messages.md#adaptive-cards)-* [Form completion feedback](~/bots/how-to/conversations/conversation-messages.md#form-completion-feedback) +* [Form completion feedback](cards-format.md#form-completion-feedback) |
platform | Cards Format | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/task-modules-and-cards/cards/cards-format.md | The following code shows an example of formatting for Markdown connector cards: +### Form completion feedback ++You can build form completion feedback using an Adaptive Card. Form completion message appears in Adaptive Cards while sending a response to the bot. The message can be of two types, error or success: ++* **Error**: When a response sent to the bot is unsuccessful, **Something went wrong, Try again** message appears. ++ :::image type="content" source="../../assets/images/Cards/error-message.png" alt-text="Error message" border="false"::: ++* **Success**: When a response sent to the bot is successful, **Your response was sent to the app** message appears. ++ :::image type="content" source="../../assets/images/Cards/success.PNG" alt-text="Success message"border="true"::: ++ You can select **Close** or switch chat to dismiss the message. ++ If you don't want to display the success message, set the attribute `hide` to `true` in the `msTeams` `feedback` property. Following is an example: ++ ```json + "content": { + "type": "AdaptiveCard", + "title": "Card with hidden footer messages", + "version": "1.0", + "actions": [ + { + "type": "Action.Submit", + "title": "Submit", + "msTeams": { + "feedback": { + "hide": true + } + } + } + ] + } + ``` ++For more information on cards and cards in bots, see [cards documentation](~/task-modules-and-cards/what-are-cards.md). + ## Adaptive Cards overflow menu Adaptive Card in Teams supports overflow menu. You can populate an overflow menu for all the secondary actions in an Adaptive Card. An overflow menu in an Adaptive Card can be added to the following: |
platform | Cards Reference | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/task-modules-and-cards/cards/cards-reference.md | To know more about Adaptive Cards, see [Adaptive Cards](/adaptive-cards/). You can now work with a hero card, which is a multipurpose card used to visually highlight a potential user selection. +Your bot can mention tags in an Adaptive Card posted into channels. For more information, see [Tag mention](../../bots/how-to/conversations/channel-and-group-conversations.md#tag-mention). + ## Hero card A card that typically contains a single large image, one or more buttons, and text. The following cards are implemented by the Bot Framework, but aren't supported b * [Work with Universal Actions for Adaptive Cards](~/task-modules-and-cards/cards/universal-actions-for-adaptive-cards/work-with-universal-actions-for-adaptive-cards.md) * [Adaptive Cards overflow menu](~/task-modules-and-cards/cards/cards-format.md#adaptive-cards-overflow-menu) * [Create connectors for Microsoft 365 Groups](../../webhooks-and-connectors/how-to/connectors-creating.md)-* [Form completion feedback](~/bots/how-to/conversations/conversation-messages.md#form-completion-feedback) +* [Form completion feedback](cards-format.md#form-completion-feedback) * [App manifest schema for Teams](../../resources/schem) |
platform | People Picker | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/task-modules-and-cards/cards/people-picker.md | You can implement People Picker for efficient task management in different scena * [Bots and SDKs](../../bots/bot-features.md) * [Build message extensions for Teams](../../messaging-extensions/what-are-messaging-extensions.md) * [Create connectors for Microsoft 365 Groups](../../webhooks-and-connectors/how-to/connectors-creating.md)+* [Tag mention](../../bots/how-to/conversations/channel-and-group-conversations.md#tag-mention) |
platform | Whats New | https://github.com/MicrosoftDocs/msteams-docs/commits/main/msteams-platform/whats-new.md | Teams platform features that are available to all app developers. | 07/21/2022 | Introduced step by step guide to send activity feed notifications | Design your app > UI components> Activity feed notifications > [Send activity feed notification](sbs-graphactivity-feedbroadcast.yml) | | 07/08/2022| Updates to send channel ID selected by user during app installation to bots via conversation and installation update events | Build bots > Bot conversations > Conversation events in your Teams bot > [Conversation events in your Teams bot](bots/how-to/conversations/subscribe-to-conversation-events.md) | | 06/16/2022 | Updated media capabilities to support desktop and mobile| Integrate device capabilities > [Integrate media capabilities](concepts/device-capabilities/media-capabilities.md)|-| 06/08/2022 | Optional card feedback for success message| Build bots > Bot conversations > [Messages in bot conversations](~/bots/how-to/conversations/conversation-messages.md#form-completion-feedback)| +| 06/08/2022 | Optional card feedback for success message| Build cards and task modules > Build cards > [Format cards in Microsoft Teams](task-modules-and-cards/cards/cards-format.md#form-completion-feedback)| | 06/03/2022 | Updated Add authentication module for enabling SSO for tab app with new structure and procedures | Add authentication > Tabs > [Enable single sign-on in a tab app](tabs/how-to/authentication/tab-sso-overview.md) | | 05/24/2022 | Additional tips for rapid approval to publish your app linked to a SaaS offer | Publish to the Teams store > Overview > [Additional tips for rapid approval to publish your app linked to a SaaS offer](~/concepts/deploy-and-publish/appsource/publish.md#additional-tips-for-rapid-approval-to-publish-your-app-linked-to-a-saas-offer) | | 05/24/2022 | Submit your Outlook- and Office-enabled apps to the Teams store | Extend your app across Microsoft 365 > [Overview](m365-apps/overview.md) | Teams platform features that are available to all app developers. | 02/08/2022 | Introduced step-by-step guide to create Calling and Meeting bot| Build bots > Calls and meetings bots > Register calls and meetings bot > [Step-by-step guide to create Calling and Meeting bot](sbs-calling-and-meeting.yml) | | 02/02/2022 | Introduced app manifest version 1.12 | App manifest > [App manifest schema](resources/schem) | | 01/25/2022 | Send real-time captions API | Build apps for Teams meetings > Meeting apps API references> [Advanced meeting APIs](apps-in-teams-meetings/meeting-apps-apis.md)|-| 01/19/2022 | Adaptive Cards form completion feedback | Build bots > Bot conversations > Messages in bot conversations > [Form completion feedback](bots/how-to/conversations/conversation-messages.md#form-completion-feedback)| +| 01/19/2022 | Adaptive Cards form completion feedback | Build cards and task modules > Build cards > [Format cards in Microsoft Teams](task-modules-and-cards/cards/cards-format.md#form-completion-feedback)| | 01/17/2022 | People Picker in Adaptive cards for desktop | Build cards and task modules > Build cards > [People Picker in Adaptive Cards](task-modules-and-cards/cards/people-picker.md)| </details> Developer preview is a public program that provides early access to unreleased T **2023 July** +* ***July 31, 2023***: [Bots can mention tags in Adaptive Cards](bots/how-to/conversations/channel-and-group-conversations.md#tag-mention). + * ***July 13, 2023***: [Extend static tabs to group chat or meetings with a customizable experience.](tabs/what-are-tabs.md) :::column-end::: |