Microsoft Teams Done Right Series: Automating New Team Requests using Logic Apps and the Microsoft Graph API
Michael Turnley
Following David Lee’s blog post, Azure Done Right Series: Automating Azure Resource Group Requests with Logic Apps, we thought it was a good opportunity to show a similar use of Logic Apps for automating New Team Requests – all within an E3 license. If you haven’t already, head over and check out David’s article, as it provides some tips and tricks for creating Forms and Logic Apps.
When it comes to managing Microsoft Teams, workplaces will usually take one of two approaches when it comes to Team creation. They will either let everyone create their own Teams or lock down Team creation entirely.
If everyone can create their own Team, very soon there will be an unmanageable mess of Teams and associated SharePoint sites, along with duplicate team names, a Team for every sport and TV show imaginable, and Teams that get created and never used. Additionally, allowing users to create teams grants Office365 group creation rights, which many organisations are not comfortable with.
The alternative is to lock down Teams creation to IT. This puts pressure on IT Teams, loading them up with simple tasks, and wasting time that could be better spent elsewhere. Most IT departments are busy, so there will be an inherent delay in having the Team approved and manually created. This slows down collaboration when users need to create Teams to get their job done.
To address the Teams creation issue, a quick solution we implemented recently for a client was to use an email-based approval workflow using Microsoft Forms, Azure Logic Apps and the Microsoft Graph API.
This allowed for any user to request a new Team quickly and easily, and the person responsible for approving new teams could have the Team created just by clicking a single “approve” button in an email.
Overview
An overview of the process is as follows:
Microsoft Forms will be used as the mechanism for a new team request
The form will supply the following information
Team Requestor/Owner
Team Name
Team Description
Justification
Form submission will trigger the Logic App, which will
start an email approval process
If approved, utilise an Azure App Service Principal to create the Team via the Microsoft Graph API
Add the team to a lifecycle policy (It’s good practice)
Notify the requestor that their team has been approved and created, or rejected.
Send notification emails if there are failures in creating a team or adding to policy.
The Logic App will require a service account for reading form responses and sending email notifications
It’s worth noting that we could use Automate (AKA Microsoft Flow) instead of a Logic Apps, however an automated workflow that can communicate with an App Service requires a full power app or power automate license.
A Logic app provides the same functionality but will be charged on a per-execution basis. Unless we are executing hundreds of times per day, a Logic App will be much more cost effective than a Power Automate license. Fun fact – Power Automate sits on top of the same platform as Logic Apps!
Create a service account
The Logic App should run under an account that does not belong to a user, so if there isn’t one already available, create a service account for Office 365 automation. This account will require an Office 365 license to access Microsoft Forms, and a mailbox to send workflow emails.
Creating the request form
Head over to Microsoft Forms, sign in with the service account, and create a form that will capture the following information:
Team Name
Team Description
Request Justification
Select the Only People in my Organisation can respond and Record Name options in form Settings. The form thank you message can also be customised here.
Creating the Azure App Service Principal
Within portal.azure.com, navigate to the Azure Active Directory pane and select App Registrations to create a New App Registration
For the Name use something descriptive like “Logic Apps MS Teams Automation Service Principal”
For the account type, use the default: Accounts in this organisational directory only ([TenantName] only – Single tenant)
A RedirectURI is not required
Assigning API Permissions
We need to assign permission to the Service Principal to allow teams creation via the Microsoft Graph API
Select API Permissions in the left pane, then Add a permission
Microsoft Graph will be listed under Commonly used Microsoft APIs, select it
Select Application Permissions
Search for Directory
Select Directory.Read.ReadWrite.All
Search for Group
Select Group.ReadWrite.All
Search for User
Select User.Read.All
Select Add Permissions
Permissions will be added and prepared for Administrator consent.
After a short delay, click the “Grant admin consent for ” button. We will need to sign in with an account that has rights to grant consent (Global Administrator) and Accept the requested permissions.
After assigning the “User.Read.All” permission, the default delegated “User.Read” permission is no longer required, so click the ellipsis next to “User.Read” and remove it. Once removed, revoke admin consent to remove it entirely.
Our final API Permissions will be as per below:
These permissions are required so that the service principal can perform all the necessary functions in our tenant to create Teams via the Graph API. We are assigning Application permissions rather than Delegated permissions. Application permissions allow an application in Azure Active Directory to act as its own entity, rather than on behalf of a specific user. Delegated permissions allow an application in Azure Active Directory to perform actions on behalf of a particular user.
Create a Client Secret
The logic app requires authentication to connect to our app service. To do this, we need to create a client secret. A good choice is to use Azure Key Vault and Azure Automation to take care of managing and rotating secrets. However, for this example we will keep it simple and create a secret with a set expiry within our app service principal. Once the secret expires, we will need to renew it and update our Logic App.
Open the Certificates & Secrets pane and create a New Client Secret
Provide a Description and define an expiry period – 1 year is fine
Once you click Add, the new Client Secret will be displayed (obfuscated in red below)
Note this down as you won’t be able to retrieve it later. You should treat this secret as you would credentials to any privileged account in your tenancy
Once you have the secret recorded in a secure location return to the Overview pane
Make note of the Client ID and the Directory ID. These plus the secret will be how you provide access to the Logic App
Lifecycle Policy
It’s good practice to assign a Lifecycle Policy to your Office 365 groups so they are removed when no longer in use. However, since you probably don’t want to enable expiry for every group in your tenant, the policy will be applied selectively. It’s important that newly created Teams have the policy applied, so our Logic App will complete this step for us.
If you are not using expiration, or are applying expiration to all groups, you can skip this section.
Within portal.azure.com, navigate to the Azure Active Directory pane and select Groups
In the left pane, select Expiration
Select a Group lifetime and Email Contact
Select Selected for Office 365 groups
Once we have created the Lifecycle policy, we will need to retrieve the ID of the policy so we can use it in the logic app.
The easiest way is via PowerShell with the Get-AzureADMSGroupLifecyclePolicy command, which is part of the AzureAD PowerShell module. Make note of the Id for later.
Create the Logic App
We now have everything we need to create the Logic App. We will need to add the Logic App to either an existing or a new resource group.
pen the Logic App Designer and select a Blank Template to start
Search for Microsoft Forms and use the option When a new response is submitted
We will need to connect to Forms, so we use our service account created earlier.
Select the New Team Request form
Add a new step, Get response details, and in the Form Id field select the form
For Response Id select Add Dynamic Content, and List of response notifications Response Id (you may need to click “See more” before you can choose this option.)
We now need to initialise some variables for use in our Logic App.
Select New step, Variables, and Initialise variable.
Create the following Variables of type String, using the values noted earlier
directory_Id
The Id of our azure tenant
application_id
Id of our service principal
secret
The client secret for our service principal
lifecycle_policy
The Id of our tenant’s lifecycle policy
Whilst it’s not needed, for readability it’s nice to give each initialise variable step a descriptive name as well.
It’s possible that we might have users complete the form and accidentally add leading or trailing spaces to responses.
If we take form data and use it exactly as entered, there could be situations where bad data could cause certain steps in our Logic App to fail.
In this case we will create sanitised variables from user input, by using the trim function. Trim removes all spaces from a string of text except for single spaces between words.
It’s good practice to always sanitise user input so it’s more difficult to abuse or pass bad data. In this case we are sanitising input purely for app functionality, not for security, which is a whole other topic (maybe for another blog post!).
Create another variable of type string, and in the dynamic content pane select Expression. In the value field enter trim()
Move your cursor to between the () and add dynamic content, Team Name. The expression will be created. Click ok
Repeat the process for Team Description, and the logic app should look like:
It’s now time to start the workflow with an approval email.
Add a new step, and search for approval email
Select Send approval email Office 365 Outlook. Sign in with the service account if prompted
The fields in the approval can be customised, using dynamic content where appropriate. User Options must be Approve, Reject.
The next step will handle the approval results.
Add a new step. Under Choose an action, select Built-in, then Control and Condition
In the choose a value field, add dynamic content, and enter SelectedOption is equal to Approve
As it’s a single step, we will complete the If false branch first. We would like to notify the requestor via email if their request for a new team was denied.
Add an action of Send an email (V2) inside the If false branch
Use dynamic content to construct the email response
In the If true branch we will create the new team, utilising our App service and the Microsoft Graph API. A useful tool for constructing Graph API calls is the Graph Explorer. If you sign into to the explorer with an account that has the required access rights, you can easily test API calls and view output.
Our first step is a GET request to retrieve the Id of the requestor – the user we will be assigning as team owner.
Add an action and select HTTP
Select GET as the method
In the URI field enter https://graph.microsoft.com/beta/users/?$select=id
Use dynamic content to insert Responders Email after “users/” and before the “? “
For Authentication, Select Active Directory OAuth
Use the directory_id variable for the Tenant
Use the application_id variable for the Client ID
Enter https://graph.microsoft.com as the Audience
Select Secret for the credential type
Use the Secret variable for the secret
Add a new action.
Search for json and select Parse JSON
Using Dynamic Content, select Body from the HTTP GETuser Id section
As we add more steps to the Logic App, it becomes more important to name our actions so we can ensure we are selecting the right content.
Tip: If you have a payload from a HTTP GET, you can utilise the “Use sample payload to generate schema” link in the Parse JSON action. The Schema will be automatically constructed for you. The Graph Explorer is an easy way to retrieve a payload from an API call.
The next action will create the Team and add the requestor as the team owner.
Add a HTTP action
Select POST as the method
Enter https://graph.microsoft.com/beta/teams as the URI
Re-use the same Authentication methods from the earlier HTTP action
After creating the team, we should add a delay step, as we will shortly be querying the new team name, and it can often take a minute to complete the team creation.
Following delay step, we can check the check the response status code from the HTTP POST for a 202 success.
Add a Condition
Again, we will deal with the false condition first, and send an email notifying of team creation failure. It’s useful to customise the email with some information so we know where the Logic App failed.
If you are applying a lifecycle policy to all O365 Groups, or not using one at all (not recommended) the logic app is complete, and you can finish the app by notifying user via email that their Team was created.
If you are selectively applying a lifecycle policy, our next step is to add the newly created team to that policy.
To be able to add our team to the lifecycle policy, we need to retrieve the policy Id.
Add an HTTP GET action under the If true section.
The URI will be:
https://graph.microsoft.com/beta/groups?$filter=displayName eq '@{variables('TeamName')}' and groupTypes/any(c:c+eq+'Unified')&$select=id
Re-use the same Authentication methods from the earlier HTTP action
We need to take the output from the HTTP GET, and select the id
Add a Parse JSON step, Add the following code to the Schema field
Use the Dynamic content picker to add in the id output from the Parse JSON step
As soon as we use the id field, the Logic App will automatically create a “For Each” step for us around the HTTP POST section. This is because the response is provided as an array
Once the POST completes, we need to add a condition to check for return code 200, indicating that the POST was successful, and if it was, send an email to the requestor letting them know their group has been created.
Our logic app is complete! All that remains is to share the form with staff, and we have an automated, simple, and repeatable method of creating new Teams with an easy approval workflow.
We can monitor logic app runs via the Overview pane, where any failures or issues will be highlighted. The runs history pane is especially useful as we can drill into each step and review the results of individual steps.
About Arinco
If you or your organisation wish to find out more about how Arinco can help you with our Teams Done Right approach to designing, implementing and managing Microsoft Teams, please reach out to us via our website.
In this post we will cover a simple solution for enabling AD Connect to mark users as Azure AD B2B “Guests”, allowing organisations to reduce complexity and adopt B2B licensing benefits.
Recently I have been working with Terraform to deploy Azure resources for a customer and needed an easy way to retrieve the resource id of an Azure resource and share it between configurations.
In this post, we walk you through the process of configuring Azure Arc on a Kubernetes cluster. Arc enables administrators with a single control plane across multi-cloud workloadss
Automatic group provisioning from Azure AD to Google Workspace (G-Suite). Google requires all objects have an email address, so usually we are restricted to mail-enabled groups. This post shows how we can auto-provision Azure AD Security groups.
In this post, we walk you through the process of configuring Azure Arc on on-premise virtual machines. Azure Arc enables administrators with a single control plane across multi-cloud environments