{"id":4864,"date":"2020-06-22T13:22:58","date_gmt":"2020-06-22T20:22:58","guid":{"rendered":"https:\/\/officedevblogs.wpengine.com\/?p=4864"},"modified":"2020-06-22T13:22:58","modified_gmt":"2020-06-22T20:22:58","slug":"a-lap-around-microsoft-graph-toolkit-day-10-microsoft-graph-toolkit-teams-provider","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/a-lap-around-microsoft-graph-toolkit-day-10-microsoft-graph-toolkit-teams-provider\/","title":{"rendered":"A Lap around Microsoft Graph Toolkit Day 10 \u2013 Microsoft Graph Toolkit Teams Provider"},"content":{"rendered":"<p><strong>Author<\/strong>: Simon \u00c5gren, Microsoft Office Development MVP<\/p>\n<p><a class=\"Hyperlink SCXW7334628 BCX7\" href=\"https:\/\/twitter.com\/agrenpoint\" target=\"_blank\" rel=\"noreferrer noopener\"><span class=\"TextRun Underlined SCXW7334628 BCX7\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW7334628 BCX7\" data-ccp-charstyle=\"Hyperlink\">@AgrenPoint<\/span><\/span><\/a><span class=\"TextRun SCXW7334628 BCX7\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW7334628 BCX7\">|\u00a0<\/span><\/span><a class=\"Hyperlink SCXW7334628 BCX7\" href=\"https:\/\/github.com\/simonagren\" target=\"_blank\" rel=\"noreferrer noopener\"><span class=\"TextRun Underlined SCXW7334628 BCX7\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW7334628 BCX7\" data-ccp-charstyle=\"Hyperlink\">GitHub<\/span><\/span><\/a><span class=\"TextRun SCXW7334628 BCX7\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun SCXW7334628 BCX7\">\u00a0|\u00a0<\/span><\/span><a class=\"Hyperlink SCXW7334628 BCX7\" href=\"https:\/\/www.linkedin.com\/in\/simonaagren\" target=\"_blank\" rel=\"noreferrer noopener\"><span class=\"TextRun Underlined SCXW7334628 BCX7\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"none\"><span class=\"NormalTextRun SCXW7334628 BCX7\" data-ccp-charstyle=\"Hyperlink\">LinkedIn<\/span><\/span><\/a><span class=\"EOP SCXW7334628 BCX7\" data-ccp-props=\"{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}\">\u00a0<\/span><\/p>\n<p>Welcome to Day 10 of the <a href=\"https:\/\/aka.ms\/mgtlap\">Microsoft Graph Toolkit blog series<\/a>!<\/p>\n<p><span class=\"TextRun BCX7 SCXW154011459\" lang=\"EN-US\" xml:lang=\"EN-US\" data-contrast=\"auto\"><span class=\"NormalTextRun CommentStart BCX7 SCXW154011459\">Microsoft Teams <\/span><\/span>plays an increasingly critical role in the remote collaboration and productivity work landscape. Teams applications can help you create collaboration and productivity solutions tailored to your organization\u2019s needs. Microsoft Graph Toolkit (MGT) makes building Microsoft Teams solutions even easier.<\/p>\n<p>In today\u2019s blog, you will get more acquainted with the MGT Teams provider and we will show you how to create an MGT-powered personal tab in Microsoft Teams.<\/p>\n<h3>Setting things up<\/h3>\n<p>Let\u2019s start by creating a simple HTML application, just as Elise showed you in the <a href=\"https:\/\/developer.microsoft.com\/en-us\/microsoft-365\/blogs\/a-lap-around-microsoft-graph-toolkit-day-2-zero-to-hero\/\">Day 2<\/a> post, and then build upon that scenario to make it work inside of Microsoft Teams.<\/p>\n<h4>Create the base HTML application<\/h4>\n<p>Start off by following all the steps in the post, and then come right back. I\u2019ll just go grab a coffee meanwhile\u2026<\/p>\n<p>\u2026now that you\u2019ve registered an Azure AD application, created an HTML application, added Microsoft Graph Toolkit, the MSAL Provider and the components, you should have a page that looks something like this:<\/p>\n<p><img decoding=\"async\" class=\"alignleft wp-image-4865\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/1-web-app-with-mgt-login-and-mgt-agenda-components-1024x555.png\" alt=\"web app with mgt-login and mgt-agenda components\" width=\"650\" height=\"353\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/1-web-app-with-mgt-login-and-mgt-agenda-components-1024x555.png 1024w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/1-web-app-with-mgt-login-and-mgt-agenda-components-300x163.png 300w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/1-web-app-with-mgt-login-and-mgt-agenda-components-768x417.png 768w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/1-web-app-with-mgt-login-and-mgt-agenda-components.png 1344w\" sizes=\"(max-width: 650px) 100vw, 650px\" \/>\nIf you end up with an error stating that your <strong>reply-url<\/strong> is incorrect, make sure to check if your browser is running the application from <a href=\"http:\/\/localhost:3000\"><strong>http:\/\/localhost:3000<\/strong><\/a> or <a href=\"http:\/\/localhost:3000\/index.html\"><strong>http:\/\/localhost:3000\/index.html<\/strong><\/a>. Since you configured the <strong>reply-url<\/strong> to work with the first case, you could add an additional <strong>reply-url<\/strong> or make a slight change to the MSAL provider and specify the <strong>redirect-uri<\/strong>:<\/p>\n<pre class=\"lang: decode:true\">&lt;mgt-msal-provider\u00a0\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0client-id=\"[YOUR-CLIENT-ID]\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0redirect-uri=\"http:\/\/localhost:3000\"&gt;\n&lt;\/mgt-msal-provider&gt;<\/pre>\n<h4>Additional prerequisites<\/h4>\n<p>Now to continue, you will need to install the tools and manage the settings listed below.<\/p>\n<ul>\n<li>Install <a href=\"https:\/\/ngrok.com\/download\">ngrok<\/a> to host your application over a public facing URL using HTTPS.<\/li>\n<li>Enable <a href=\"https:\/\/docs.microsoft.com\/en-us\/MicrosoftTeams\/teams-custom-app-policies-and-settings#org-wide-custom-app-setting\">Custom Teams apps and custom app uploading<\/a> (if you are using a developer tenant, this should already be configured)<\/li>\n<li>Install <a href=\"https:\/\/docs.microsoft.com\/en-us\/microsoftteams\/platform\/concepts\/build-and-test\/app-studio-overview#installing-app-studio\">App Studio<\/a><\/li>\n<\/ul>\n<h3>Make some visual changes<\/h3>\n<p>If you followed this series during season one you learned about things like <a href=\"https:\/\/developer.microsoft.com\/en-us\/graph\/blogs\/a-lap-around-microsoft-graph-toolkit-day-5-customizing-components-using-templates\/\">using templates<\/a>, adding <a href=\"https:\/\/developer.microsoft.com\/en-us\/graph\/blogs\/a-lap-around-microsoft-graph-toolkit-day-4-customizing-components\/\">custom CSS<\/a> and the <a href=\"https:\/\/developer.microsoft.com\/en-us\/graph\/blogs\/a-lap-around-microsoft-graph-toolkit-day-6-the-power-of-mgt-get\/\">power of mgt-get<\/a>. Let\u2019s apply some of that learning and incorporate some HTML and CSS.<\/p>\n<p>First, remove the <strong>mgt-agenda<\/strong> component. In its place, add some HTML where we are using <strong>mgt-get <\/strong>in order to get all of your Microsoft Teams teams. Then, we use templates to display each Team with the <strong>display name<\/strong> and <strong>description<\/strong>. We also make use of the <strong>mgt-people <\/strong>component to display the users in the Team.<\/p>\n<pre class=\"lang: decode:true\">&lt;mgt-get resource=\"\/me\/joinedTeams\" scopes=\"User.Read.All\"&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;template&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div class=\"header\"&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h1&gt;My Joined Teams&lt;h1&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h2&gt;And\u00a0\u00a0members&lt;\/h2&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div class=\"teams\" data-for=\"team in value\"&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h3&gt;{{ team.displayName }}&lt;\/h3&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0&lt;div data-if=\"team.description\" class=\"description\"&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{{ team.description }}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;div data-else class=\"description\"&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Team description is empty\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;h4&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;mgt-people show-max=\"10\" group-id={{team.id}}&gt;&lt;\/mgt-people&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/h4&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0&lt;\/div&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;\/template&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;template data-type=\"loading\"&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Loading...\n\u00a0\u00a0\u00a0\u00a0&lt;\/template&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;template data-type=\"error\"&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{{ this }}\n\u00a0\u00a0\u00a0\u00a0&lt;\/template&gt;\n&lt;\/mgt-get&gt;<\/pre>\n<p>Now add some CSS inside of style tags, in the header of the code:<\/p>\n<pre class=\"lang: decode:true\">&lt;style&gt;\n\u00a0\u00a0\u00a0\u00a0body {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0 background-color: #FFF;\n\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0.header {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0background-color: #6264A7;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0text-align: center;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0color: #F3F2F1;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0padding: 20px 10px;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0margin: 8px 4px;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0box-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0.teams {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0background-color: #F3F2F1;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0padding: 10px;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0margin: 8px 16px;\n\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0.teams:hover {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0box-shadow: 0 3px 14px rgba(0, 0, 0, 0.3);\n\u00a0\u00a0\u00a0\u00a0}\n&lt;\/style&gt;<\/pre>\n<p>Now, when you log into the application, it should look something like this when you hover over a user from the Team:<\/p>\n<p><img decoding=\"async\" class=\"alignleft wp-image-4866\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/2-web-application-with-user\u2019s-joined-teams-list.png\" alt=\"web application with user\u2019s joined teams list\" width=\"550\" height=\"495\" \/><\/p>\n<h3>Turning your web app into a Teams Tab<\/h3>\n<p>Microsoft Teams tabs are webpages hosted outside of Teams that are embedded in an Iframe as a part of a channel, group chat or as a personal app for an individual user. They are context-aware and can grab some Teams-specific information based on where they are embedded.<\/p>\n<p>Our goal today is to make the required changes that allows our HTML application to work both outside and inside of Microsoft Teams. The content surfaced in Teams must be hosted on a publicly available URL available using HTTPS.<\/p>\n<p>In production scenarios we would host the application somewhere else, like an <strong>Azure web service<\/strong>, and instead use the URL to that application.<\/p>\n<h4>Step 1: Add the Teams SDK<\/h4>\n<p>The Microsoft Teams SDK is not included in MGT in case you want to run different versions of the SDK.<\/p>\n<p>First, add a reference to the <a href=\"https:\/\/docs.microsoft.com\/en-us\/javascript\/api\/overview\/msteams-client\">Microsoft Teams JavaScript Client SDK<\/a> using script tags, <strong>before <\/strong>the Microsoft Graph Toolkit.<\/p>\n<pre class=\"lang: decode:true \">&lt;script src=\"https:\/\/unpkg.com\/@microsoft\/teams-js\/dist\/MicrosoftTeams.min.js\" crossorigin=\"anonymous\"&gt;&lt;\/script&gt;<\/pre>\n<h4>Step 2: Add the Teams Provider<\/h4>\n<p>We need a Microsoft Graph Toolkit provider to enable our components to call Microsoft Graph to retrieve and render data. The provider takes care of getting the necessary access token with the requested scopes, so we don\u2019t need to write a bunch of code to implement all of the auth logic.<\/p>\n<p>The Teams Provider, is a wrapper around the MSAL provider. It handles the Teams-specific logic, so you don\u2019t have to create the necessary code to handle the interactions with the Teams SDK and all of the authentication redirects to authenticate the user. In true MGT spirit, you take care of the imports and configuration, and the Teams Provider does the heavy lifting.<\/p>\n<p>Normally, we would need to make a call to microsoftTeams.initialize() in order to display the page in Microsoft Teams. In our case the <strong>MGT Teams Provider <\/strong>takes care of it.<\/p>\n<p>As mentioned earlier, we want this application to work both inside and outside of Microsoft Teams. To do this we have two options.\u00a0 The first option is to add the provider component <strong>mgt-teams-provider<\/strong> and keep the <strong>mgt-msal-provider <\/strong>with slight alterations. We can use the <strong>depends-on <\/strong>attribute in the MSAL provider to create a fallback chain. The MSAL provider will only be used if the Teams provider is not available in the current environment.<\/p>\n<pre class=\"lang: decode:true\">&lt;mgt-teams-provider\u00a0\n\u00a0\u00a0\u00a0\u00a0client-id=\"[YOUR-CLIENT-ID]\"\u00a0\n\u00a0\u00a0\u00a0\u00a0auth-popup-url=\"auth.html\"&gt;\n&lt;\/mgt-teams-provider&gt;\n\n&lt;mgt-msal-provider\u00a0\n\u00a0\u00a0\u00a0\u00a0client-id=\"[YOUR-CLIENT-ID]\"\n\u00a0\u00a0\u00a0\u00a0depends-on=\"mgt-teams-provider\"\u00a0\n\u00a0\u00a0\u00a0\u00a0redirect-uri=\"http:\/\/localhost:3000\"&gt;\n&lt;\/mgt-msal-provider&gt;<\/pre>\n<p>The other option is to use code.\u00a0 We\u2019ll do this because it gives us more control and we could use it (in a similar fashion) in more complex, code-based applications further down the road. We add a script tag with the code after all the components in the body:<\/p>\n<pre class=\"lang: decode:true\">&lt;script&gt;\n\u00a0\u00a0\u00a0\u00a0let provider;\n\u00a0\u00a0\u00a0\u00a0if (mgt.TeamsProvider.isAvailable) {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0provider = new mgt.TeamsProvider({\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0clientId: \"[YOUR-CLIENT-ID]\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0authPopupUrl: \"\/auth.html\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0} else {\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0provider = new mgt.MsalProvider({\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0clientId: \"[YOUR-CLIENT-ID]\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0redirectUri: \"http:\/\/localhost:3000\",\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0});\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0mgt.Providers.globalProvider = provider;\n&lt;\/script&gt;<\/pre>\n<h4>Step 3: ADD ONE LINE OF CODE!<\/h4>\n<p>First, create the <strong>auth.html <\/strong>page in the root of the application (same level as index.html). This is the page that will handle the auth in the popup (authPopupUrl). Once again, we add script tag references to the Teams SDK and to MGT. Then we only need to add <strong>ONE <\/strong>line of code <strong>mgt.TeamsProvider.handleAuth() <\/strong>to make the Teams Provider handle everything for us:<\/p>\n<pre class=\"lang: decode:true\">&lt;html&gt;\n\u00a0\u00a0&lt;head&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;script src=\"https:\/\/unpkg.com\/@microsoft\/teams-js\/dist\/MicrosoftTeams.min.js\" crossorigin=\"anonymous\"&gt;&lt;\/script&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;script src=\"https:\/\/unpkg.com\/@microsoft\/mgt\/dist\/bundle\/mgt-loader.js\"&gt;&lt;\/script&gt;\n\u00a0\u00a0\u00a0\u00a0&lt;script&gt;\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0mgt.TeamsProvider.handleAuth();\n\u00a0\u00a0\u00a0\u00a0&lt;\/script&gt;\n\u00a0\u00a0&lt;\/head&gt;\n\u00a0\u00a0&lt;body&gt;&lt;\/body&gt;\n&lt;\/html&gt;<\/pre>\n<p>With all this time we are saving, maybe there\u2019s time for another coffee.<\/p>\n<h3>Testing the app in Microsoft Teams<\/h3>\n<h4>Step 1: Start the application in the browser<\/h4>\n<p>Start the application via <strong>Live Server<\/strong> by either right-clicking on the index.html file in the Explorer pane and click Open with Live Server, or using the shortcut <strong>ALT+L ALT+O<\/strong>. \u00a0The server will start and automatically open your index.html page in your default browser at http:\/\/localhost:3000.<\/p>\n<p>You don\u2019t need to log in or anything, just don\u2019t close the browser tab.<\/p>\n<h4>Step 2: Start ngrok<\/h4>\n<p>Run this command:<\/p>\n<pre class=\"lang: decode:true\">ngrok http 3000 --host-header=localhost<\/pre>\n<p><img decoding=\"async\" class=\"alignleft wp-image-4867\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/3-forwarded-ngrok-address-shown-in-terminal.png\" alt=\"forwarded ngrok address shown in terminal\" width=\"650\" height=\"229\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/3-forwarded-ngrok-address-shown-in-terminal.png 768w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/3-forwarded-ngrok-address-shown-in-terminal-300x106.png 300w\" sizes=\"(max-width: 650px) 100vw, 650px\" \/><\/p>\n<h4>Step 3: Add reply-url<\/h4>\n<p>Find the Azure AD application registration you created earlier in the Azure Portal. Move into <strong>Authentication<\/strong> and add the <strong>https <\/strong>URL from <strong>ngrok<\/strong> with trailing <strong>\/auth.html<\/strong>.<\/p>\n<p><img decoding=\"async\" class=\"alignleft wp-image-4868\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/4-redirect-uri-setup-in-Azure-portal-1024x350.png\" alt=\"redirect uri setup in Azure portal\" width=\"650\" height=\"222\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/4-redirect-uri-setup-in-Azure-portal-1024x350.png 1024w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/4-redirect-uri-setup-in-Azure-portal-300x103.png 300w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/4-redirect-uri-setup-in-Azure-portal-768x263.png 768w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/4-redirect-uri-setup-in-Azure-portal.png 1251w\" sizes=\"(max-width: 650px) 100vw, 650px\" \/><\/p>\n<h4>Step 4:\u00a0 Create app in App Studio<\/h4>\n<p>To create an app in Microsoft Teams you need an icon and a manifest file that points to the location where the actual application is hosted.\u00a0 To build a manifest for our app we\u2019ll use App Studio, which is very user-friendly.<\/p>\n<p>First, start Microsoft Teams. I recommend using the web version, since you could use the browser debug tools. But using the desktop client is fine as well.<\/p>\n<p>Launch App Studio from your apps, go into the <strong>Manifest editor<\/strong> tab and create a new app. Then fill in the required fields<\/p>\n<p><img decoding=\"async\" class=\"alignleft wp-image-4869\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/5-app-details-view-in-Teams-App-Studio-1024x491.png\" alt=\"app details view in Teams App Studio\" width=\"650\" height=\"312\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/5-app-details-view-in-Teams-App-Studio-1024x491.png 1024w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/5-app-details-view-in-Teams-App-Studio-300x144.png 300w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/5-app-details-view-in-Teams-App-Studio-768x369.png 768w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/5-app-details-view-in-Teams-App-Studio.png 1338w\" sizes=\"(max-width: 650px) 100vw, 650px\" \/><\/p>\n<p>In the left pane, click on <strong>Tabs<\/strong> and select to <strong>Add a personal tab <\/strong>and fill in the values (using the <strong>ngrok<\/strong> url)<\/p>\n<p><img decoding=\"async\" class=\"alignleft wp-image-4870\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/6-personal-tab-view-in-Teams-App-Studio.png\" alt=\" personal tab view in Teams App Studio\" width=\"550\" height=\"428\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/6-personal-tab-view-in-Teams-App-Studio.png 751w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/6-personal-tab-view-in-Teams-App-Studio-300x234.png 300w\" sizes=\"(max-width: 550px) 100vw, 550px\" \/><\/p>\n<p>In the left pane, click on <strong>Test and distribute <\/strong>and then <strong>Download <\/strong>your app package. Then go back to <strong>Apps<\/strong> in Microsoft Teams, click on <strong>Upload a custom app <\/strong>and <strong>upload for &lt;Tenant name&gt;<\/strong>.<\/p>\n<p>Select the .zip file that you just downloaded, and then add the tab.<\/p>\n<p><img decoding=\"async\" class=\"alignleft wp-image-4871\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/7-Upload-a-custom-app-option-in-Teams.png\" alt=\"Upload a custom app option in Teams\" width=\"350\" height=\"191\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/7-Upload-a-custom-app-option-in-Teams.png 415w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/7-Upload-a-custom-app-option-in-Teams-300x164.png 300w\" sizes=\"(max-width: 350px) 100vw, 350px\" \/><\/p>\n<p>Remember, the manifest points to where the application is hosted. Right now, it points to the <strong>ngrok<\/strong> tunneling URL, and the application that runs locally. We don\u2019t have to upload the .zip each time we make a code change, the changes will be reflected where it\u2019s hosted.<\/p>\n<p>If you have configured everything correctly, you should now be able to log in and see the application running inside of Microsoft Teams.<\/p>\n<p><img decoding=\"async\" class=\"alignleft wp-image-4872\" src=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/8-web-app-loaded-within-Teams-as-a-tab.png\" alt=\"web app loaded within Teams as a tab\" width=\"550\" height=\"541\" srcset=\"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/8-web-app-loaded-within-Teams-as-a-tab.png 964w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/8-web-app-loaded-within-Teams-as-a-tab-300x295.png 300w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/8-web-app-loaded-within-Teams-as-a-tab-768x756.png 768w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/8-web-app-loaded-within-Teams-as-a-tab-24x24.png 24w, https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-content\/uploads\/sites\/73\/2020\/06\/8-web-app-loaded-within-Teams-as-a-tab-48x48.png 48w\" sizes=\"(max-width: 550px) 100vw, 550px\" \/><\/p>\n<h3>To summarize<\/h3>\n<p>Great job! It might seem like many steps, but after getting to know the workflow it\u2019s quite easy.<\/p>\n<p>Basically, the steps are:<\/p>\n<ol>\n<li>Register an Azure AD app and create the HMTL application with some MGT magic.<\/li>\n<li>Host the application somewhere. If locally, we spin up <strong>ngrok<\/strong><\/li>\n<li>Create a Teams Application via <strong>App Studio<\/strong> and configure a personal tab.<\/li>\n<li>Make sure the <strong>reply-url <\/strong>in the Azure AD app, and the <strong>content url<\/strong> in the personal tab settings points to the correct URL.<\/li>\n<li>Install the application in Microsoft Teams<\/li>\n<\/ol>\n<h3>Next steps<\/h3>\n<p>Get the source code for this sample in the <a href=\"https:\/\/github.com\/microsoftgraph\/mgtLap-TryItOut\/tree\/master\/09%20-%20SharePoint%20Provider\/helloworld-mgt\">mgtLap repository<\/a>. For simplicity, we only built a simple HTML application.<\/p>\n<p>Try the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=TeamsDevApp.ms-teams-vscode-extension\">Microsoft Teams Toolkit<\/a> Visual Studio Code extension. It streamlines the development process, making it easier than ever to scaffold a new tab with your desired scope, then create and configure an app package (like App studio).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Microsoft Teams plays an increasingly critical role in the remote collaboration and productivity work landscape. Teams applications can help you create collaboration and productivity solutions tailored to your organization\u2019s needs. Microsoft Graph Toolkit (MGT) makes building Microsoft Teams solutions even easier. This article will show you end to end how to use Microsoft Graph Toolkit to build applications for Teams.<\/p>\n","protected":false},"author":69076,"featured_media":25159,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3],"tags":[34],"class_list":["post-4864","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-microsoft-graph","tag-microsoft-graph-toolkit"],"acf":[],"blog_post_summary":"<p>Microsoft Teams plays an increasingly critical role in the remote collaboration and productivity work landscape. Teams applications can help you create collaboration and productivity solutions tailored to your organization\u2019s needs. Microsoft Graph Toolkit (MGT) makes building Microsoft Teams solutions even easier. This article will show you end to end how to use Microsoft Graph Toolkit to build applications for Teams.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/4864","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/users\/69076"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/comments?post=4864"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/posts\/4864\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media\/25159"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/media?parent=4864"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/categories?post=4864"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/microsoft365dev\/wp-json\/wp\/v2\/tags?post=4864"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}