📜 ⬆️ ⬇️

Let's talk about Teams

A small interesting story about how the guys from Wrike integrated Microsoft Teams into their service and what it led to, as well as a big technical part about the integration process itself. By the way, they were one of the first in the world to do this on the day of the release of the chat.



1 + 1 = 3


In our experience at Wrike , potential buyers, choosing a project management system, are increasingly interested in available integrations. In fact, from a pleasant bonus, the adaptation of the product to the existing ecosystem has become a factor that determines the choice of the client.

Of course, it is important for developers to focus on the most common tools for corporate users, and here Microsoft products are inevitable priority. However, it is even more important not to do integration for the sake of integration. 1 + 1 should give 3, in the sense that a bundle of solutions should create additional value for the client.
')
Therefore, we have consistently added integration with Azure Active Directory, OneDrive and Office 365 to our service. The ultimate goal of these steps is to create a seamless workspace where the user will not switch between applications and copy-paste information from one window to another every few minutes. tools and services for teamwork will not lie the abyss.

MS Teams has become a logical new step. 53% of companies employing 500+ employees use corporate instant messengers ( SpiceWorks data). We thought that it would be convenient for users discussing the work to immediately implement the results of the discussion. Therefore, together with Microsoft, the team selected the most appropriate service functions in such a situation and thought through their organic implementation in the Teams interface.

As a result, Wrike users can now create projects and tasks directly from the messenger, and any project can now be added to Teams as a new tab. Integration also supports making changes to the task (status, performer, deadline, comments) in parallel with the discussion.



The discussions of the project have become more substantive and accurate, due to the possibility to show a Gantt chart with deadlines inside the messenger, so it is in front of the eyes of the participants in the discussion.



And of course, an obvious opportunity was added - notifications for your tasks can now be received not only by email, but also by messages in Teams.

The development of this functionality took 2 months. During this time, the team has gained an interesting experience that may be useful for you.

On the technical side


Any tab application for Microsoft Teams consists of:


All pages are rendered inside the Microsoft Teams iframe. Examples of a manifest for a tab application are described in MSDN . There you can also find a manifest scheme . At the time of this writing, the actual version of the scheme was 0.4.

The main fields of the manifesto:


After preparing the manifest and resources, the resulting archive can be uploaded to Microsoft Teams .

Interaction with the infrastructure of Microsoft Teams is provided by the Microsoft Teams JS API library . The library allows you to:


To use the library, it is necessary to connect it and initialize it on each page of the application:

 <script src="https://statics.teams.microsoft.com/sdk/v0.4/js/MicrosoftTeams.min.js"></script> ... <script type="text/javascript"> microsoftTeams.initialize(); </script> 

Consider an example application for MsTeams with a multi-page configuration and linking Azure AD and Wrike accounts.

The specifics of the application in several iframes (configuration, tab) and with Oauth2 redirects require a sophisticated but typed flow for both the configuration and for displaying the application in a previously added tab.

Main processes:

  1. The user adds a new tab in Microsoft Teams.
  2. Unauthorized user comes to the previously added tab.
  3. An authorized user comes to the previously added tab.

The process of adding a tab is shown in the figure below. Microsoft Teams pages are marked in blue, pages of our application are in green, code and request processing actions are shown in white.



The “Welcome page” page displays basic information about our application and the “Connect” button, which starts the authorization flow in Azure AD.

Callback URL handler must:


The “Setup page” page is a settings page. It is requested when adding a tab and through the “Configuration” option in the menu of a previously added tab (if the manifest was set to canUpdateConfig ).

Sample code to run Oauth2 authentication through a multi-tenant application in Azure AD (that is, the sample code for the Welcome page) looks like this:

 <script src="https://statics.teams.microsoft.com/sdk/v0.4/js/MicrosoftTeams.min.js"></script> <input type="button" onclick="startAuth()" value="..."/> <script type="text/javascript"> microsoftTeams.initialize(); var startAuth = function() { microsoftTeams.authentication.authenticate({ url: 'https://login.windows.net/common/oauth2/authorize' + '?response_type=code%20id_token' + '&scope=openid' + '&response_mode=' + form_post + '&client_id=' + <YOUR_AZURE_APP_CLIENT_ID> + '&resource=https%3a%2f%2fgraph.windows.net' + '&nonce=' + <MS_NONCE> + '&state=' + <OAUTH2_STATE> + '&redirect_uri=' + encodeURIComponent('http://localhost/callback'), width: 700, height: 500, successCallback: onAuthSuccess, failureCallback: onAuthFailure }); }; var onAuthSuccess = function() { console.log('Auth success'); document.location.href='http://localhost/setup'; }; var onAuthFailure = function() { console.log('Auth failed'); microsoftTeams.settings.setValidityState(false); }; </script> 

Options:


The launch of flow-authorization is provided by the microsoftTeams.authenticate method from Teams JS API. You do not need to explicitly call window.open . The onAuthSuccess , onAuthFailure are called in the context of the source page, from where the login window was opened.

A safer and more reliable timeout method to start Oauth2 flow involves a request to our handler, which will generate OAUTH2_STATE and redirect the user to login.windows.net .

Detailed information on creating and configuring applications for Azure AD can be read here .

An example of a code page “Setup page” for saving settings is shown below.

 <script src="https://statics.teams.microsoft.com/sdk/v0.4/js/MicrosoftTeams.min.js"></script> <input id="name" type="text" placeholder="Enter your name" onkeyup="validate()"/> <script type="text/javascript"> microsoftTeams.initialize(); var isNameValid = function() { return jQuery('#name').val().trim().length > 0; } var validate = function() { //    Save microsoftTeams.settings.setValidityState(isNameValid()); }; microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) { if (!isNameValid()) { saveEvent.notifyFailure("We couldn't save your tab settings. Please enter your name."); return; } microsoftTeams.settings.setSettings({ contentUrl: 'http://localhost/tabContent', suggestedDisplayName: "Your Tab Name", websiteUrl: "http://localhost" }); saveEvent.notifySuccess(); }); </script> 

Options:


The following code uses the following Teams JS API methods:


Consider the process of user login to the previously added tab. Here are the following options:

  1. The user is new, not associated with our system.
  2. User known to our system, but not authorized.
  3. Authorized user.

We have “seamless” authorization, so we’ll just add a new user to our account in our system after logging in to Azure AD. This is the login process to the previously added tab.



Recall that the organizational structure inside Microsoft Teams is as follows:


Tab settings and user information are available through context and settings (from Microsoft Teams JS API):


Challenges and Solutions


What difficulties can arise with such a structure?

The Wrike team decided that users will be authorized in Azure AD. User data: upn (user principal name or email), teamId , channelId are available through the JS API, but this data cannot be validated on the side on the backend side - only if the application in Azure AD requests rights that require admin permission. This is due to the feature of the Azure Graph API, according to which information about the structure of the organization is available only after the consent of the administrator. This approach is inconvenient because only a Azure AD admin can add a tab to a channel.

We do not know which tab the user opens, if there are several of them in the channel (we do not have a tabId , although we can generate it, but more on that below). Storage of custom settings is available only in settings.customSetting s, but access to settings not available from the tab pages, only from the configuration pages.

How to solve these problems? The collection of data on teamId , channelId , tabId can be organized during user authorization and stored on the side of our application. Requests from the user inside the tab can be validated based on data from the current context ( microsoftTeams.getContext ).

The tab identifier can be generated when adding, on the configuration page, for example, like this:

  microsoftTeams.settings.registerOnSaveHandler(function (saveEvent) { microsoftTeams.settings.getSettings(function(settings) { var tabId = generateOrGetTabId(settings); var customSettings = { tabId: tabId }; microsoftTeams.settings.setSettings({ contentUrl: 'http://localhost/tabContent?tabId=' + tabId, ... customSettings: JSON.stringify(customSettings) }); saveEvent.notifySuccess(); }) }); 

There is no access to the settings tab in the code page, so we pass the parameters to the query string for contentUrl in the query string . tabId will tabId only when you first add a tab. When reconfiguring we will use the previously specified. It is responsible for generateOrGetTabId . The settings.customSettings field allows you to store the generated tabId both as a string and as a serialized JSON object.

In conclusion, I would like to tell you about deepLinks - a way to generate a link to a tab or to specific content within a tab.

At the time of this writing, there are two ways to generate links:

  1. Interactive - using microsoftTeams.shareDeepLink . The user is prompted for a name and the link is copied to the clipboard. Such links are recognized in the chat, rendered as text entered by the user, and lead to a tab with the specified entityId and subEntityId . A detailed description is here .
  2. Non-interactive — by forming a link based on the application id (from the manifest), the context of the tab, and other parameters: entityId , subEntityId and so on. Such links can be used for various notifications, for example, in email or messages from bots.

Description of how to form deepLinks is in MSDN . Additionally, I would like to note that both methods work in the tabs page code, since they do not require the use of microsoftTeams.settings .

Teams JS API is actively developing, and in the development process, the version changed from 0.2 to 0.4. In addition, the manifest for bots and tabs has become common.

The Azure AD Graph API and the Microsoft Graph API were also used to integrate with Wrike. During the process and after the release, we had close communication with colleagues from Microsoft, and our feedback was taken into account.

Part of the wishes that the guys from Wrike voiced in the process of communication.
  • Team information must be available in the Teams JS API and / or in the Graph API.
  • Access to the microsoftTeams.settings settings is needed in the tab, and not only on the settings page.
  • There is a lack of tabId, although two types of Deep Links partially compensate for the lack of tabId.
  • You need a more flexible scopes system for Graph Oauth2 authorization, which is necessary to get the list of members of the current team (team) without involving the Azure AD Tenant admin to customize the tab.
  • More flexible configuration page settings for customizing styles, accessing native Microsoft Teams styles, and changing standard controls. Such settings will give more freedom to create Configuration Wizards.


Issues of access to the composition of the team are already solved in the Bot API . Part of the functionality for Deep Links was published shortly before the release of Teams. Perhaps Teams support at the REST API level will be implemented in the Microsoft Graph API, as this API is being actively developed and involves interaction with various components of Office 365.

By the way, the form for sending a new application for review can be found here . We hope that the Wrike experience will be useful to you, and Microsoft Teams users will be able to get even more useful tools for teamwork.

About the authors


Alexander Belyaev , product manager. Responsible for the elaboration of Job stories (within the framework of the Jobs to be Done concept) for the Wrike audience and, accordingly, for the functions that users use within the framework of typical scenarios of their work. It also develops the Wrike API and is responsible for integration with strategic partners. Loves cats and zen.

Oleg Vashenkov , backend developer. In the context of integration with Microsoft Teams, it is responsible for authorization, creation and integration of accounts, support and extension of the API for working within Teams. Loves mini hackathons - to implement ideas for new platforms and devices and try their solutions for work and life, as well as cars, including training, tuning and competitions.

We remind you that you can try Microsoft Azure for free here .

Source: https://habr.com/ru/post/327518/


All Articles