Use Graph Directory Schema Extensions for Microsoft Teams Governance

Graph and Teams

In this article, I want to share a method that allows your organization to bring a Microsoft Teams Governance solution to the next level. Most organizations that use Microsoft Teams have Governance requirements like naming conventions, Teams creation limitations, etc. Microsoft has solutions in the portfolio that help you fulfill these requirements, like creation and naming policies for Microsoft 365 Groups. Additionally, you can use solutions like the great ‚Request-a-team‘ App to regulate Team requests or third-party apps like Rencore Governance to manage teams over the whole lifecycle.

The more often we implement such Governance & Compliance solutions in the environments of our customers, we experience limitations in the data basis like additional attributes …

Here are two exemplary reasons why we need more data related to a Team, which I will use to demonstrate the usage:

  1. Naming Convention Limitations
    Most Orgs have requirements for a basic name schema. One reason for this requirement is to help the user to organize themselves. But as you know sometimes it is very hard to find a naming convention which fits the user and technical requirements. Furthermore, when it’s getting serious, there will be (legetimate) exceptions that makes a naming convention useless if you also rely on this convention when you make some mass updates or create reports.
    A custom value which defines the Teams-Type would help to manage these Teams programatically.
  2. Expiration of Teams
    Another Reason to add some ‚metadata‘ to a group is to stamp an expiration date on a Team. If a Team is created to do some project work (wich is a ‚THE‘ use case for Teams), an end date is mandatory. Microsoft has a solution which allows you to apply an expiration policy to a group, but I was never able to apply them until now because they are not granular enough for most requirements.
    If you have an end date assigned to a team you can do things with it: For example you can remove guest members, inform and enforce the owner to ‚close‘ the Team, extract as finalized documents …. An attribute which contains the defined end date could be used to start any action on a specific date.

Now that we know our requirements: How do we deal with them? A very pragmatic, and often used way to solve this, is to have a separate database for this metadata (e.g. Dataverse, SharePoint List, SQL) which is fed by a Teams deployment solution and enriched with this metadata. This is a good first approach, but you have an additional component involved that must be maintained, which generates costs, must be updated and synchronized, etc. I prefer to store the information in the AD as the central directory service.

Another approach is to use Microsoft Graph Extensions for Azure AD Object. This is the way I want to explain here. I choose this method because it allows me to store all needed metadata directly to the relevant item. This makes it easy to find and combine the relevant information in automation tasks and reports.

I am a big fan of the Microsoft Graph API and try to build nearly every custom solution with the help of the Graph first. I am not a developer but the documentation, with all the examples (, makes it easy to build your first solutions easy. Microsoft also makes it clear in every technical publication that the Graph is the way to go.

Extend the Schema

First, to be able to add metadata to a Team, you need to create a place for it. You have to decide if you use open extensions or schema extensions. Open extensions are easier to implement, but you can not use them to filter results. I’ve decided to use Schema extensions because the possibilities with them are much richer.

I will use Postman with an Azure AD App Registration using Delegated Permissions in my Example (Check out Toni Pohls Blog for more details about creating an App Registration to manage the custom extensions). You can also use Graph Explorer to do the same.

Create custom extension

As you can see I’ve made a Post Request to the Graph URL:

The parameters you need to define are id, targetTypes and properties and owner, the parameter description is optional.

id: The id (=schema extension name) has to be unique in the tenant. You can add a defined prefix for the id (here thin4matics_) when you have a custom Top Level Domain configured in your tenant. If you do not define a prefix, a random string will be created as a prefix.

You can only use a Top Level Domain as a prefix if you have a .com/.net/.gov/.edu/org Domain registered in your Tenant. So, for non-US tenants it could be a consideration to add a custom domain, especially in case you want to have a clear name for your extension.

targetTypes: This parameter defines which objects the schema extension can be used. We choose Group because we only want to enrich Teams (which were based on Microsoft 365 Groups) with that metadata.

properties: These are the keys that we want to use in our Governance story. Possible types are String, DateTime, Boolean, Integer and Binary. We’ve created two keys:
– GroupType (String): handle the exemplary reason 1 (Naming Convention Limitations)
– endDate (DateTime): handle the exemplary reason 2 (Expiry of Teams)

owner: Here you have to insert an AppID of an App Registration where your admin account, which you’re using to create the extension. In my example, where I’m using postman with an existing app Registration, the owner ID is automatically set to the App ID which is used by postman. If you’re creating the app registration via Graph Explorer, you have to provide an AppID as owner value. (See this link for more information: Create schemaExtension – Microsoft Graph v1.0 | Microsoft Docs)

After you’ve defined the properties and decided to use the schema extension as defined, you have to set the status of the extension from ‚InDevelopment‘ to ‚Available‘. As long as you do not set the status to available, only the owner (if not defined in the request, the owner is the requestor, here the ID of the used App Registration) can use the schema extension.

Use a ‚Patch‘ Request to update the Schema Extension to ‚Available‘. You must include the owner (here the ID of the used App Registration) and the new Status in the Request against your Schema-Extension
Update custom extension

You will not receive a response here. StatusCode ‚204‘ shows that the request was successful. You can start a Get Request against the Extension to prove it:

Get custom extension

Now you have successfully implemented your custom Extension. But how can we insert data here?

Write data in custom schema extensions

Now that we have created the custom extension and made it available we can use it to tag our Teams and other M365 Groups with additional information. To create Teams in a regulated environment we use mostly the Graph. Graph requests can be initiated for example from PowerAutomate, LogicApps or Powershell. The Graph request can now easily be extended with the new attributes.

Graph request to create a new Group with custom extensions:

New Group with custom extensions

As you can see we just have to extend the POST Request with the new extension keys and their values:

    "thin4matics_thinGovernance": {
        "M365GroupType": "Teams:Functional",
        "endDate": "2022/10/14"

If you already have some Teams out there that you want to update with Governance Informations you can use a PATCH Request against the Group:

Update existing group with custom extensions

Now you have successfully added custom information to your Teams. This specific information will help you and your org keep the overview, especially in larger organizations. Next, I will show you how to use these attributes in searches.

Search and Filter for custom attributes

To find all Teams with the specific information you can use a GET Request in the Microsoft Graph API. You can use the filter method to only get specific results. Here is an example request which only returns Teams with the GroupType „Teams:Functional“. We just need to add the Filter „$filter=thin4matics_thinGovernance/M365GroupType eq ‚Teams:Functional'“ to the Get Request.$filter=thin4matics_thinGovernance/M365GroupType eq 'Teams:Functional'&$select=id,mailnickname,thin4matics_thinGovernance

If you want to find every Team, where the End Date was reached you can use a Get Request like this:$filter=thin4matics_thinGovernance/endDate le '2021/10/14'&$select=id,mailnickname,thin4matics_thinGovernance

The filter “ $filter=thin4matics_thinGovernance/endDate le ‚2021/10/14′“ will list all Teams where the End Date is less or equal to the specific date.

Filter for custom attributes

Now you have seen how to use the custom extensions in searches which helps you organize your Teams environment.

Downsides of this approach

As in nearly every custom solution, there are also ‚challenges‘.

Custom Attributes were not displayed in any GUI. So, no Helpdesk Admin can check the Values in the custom attributes of a Group using the regular Azure Active Directory Management Portal. To use the values you need a programmatic way to use them, or build your own ‚View Interface‘. Because you could use the Graph and PowerApps etc. to build a view, this challenge is not as difficult as it sounds, but you have to do it if you have a need for a graphical interface.

Also, the users can not see the values of these attributes without building them a view, synchronize the data to a List in the related Team, or something similar.

Become creative and make things…

I hope you now have an idea of how custom extensions can help your organization to structure your environment. The more I work with the extension, the more use cases come up. Like:

  • Add Access Package or Access Package Catalog Informations to a Group to simplify operation
  • Add customer specific Project-Information (like a project number) to a Group
  • Implement a ‚HiddenFromInventory‘ switch (because the existing one is deprecated)

Once you have added valuable information to M365 Groups you won. The possibilities of what you can do with that information now are huge. You can, for example, build a LogicApp that runs daily and finds every ‚expired‘ Team and informs the Owners to finalize or extend it. You can build PowerShell Scripts and use them in Azure Runbooks to build reports and statistics with that data. Project Managers can request reports for related Teams easily, …

Thank you for reading. Any feedback is welcome!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert