Contents
- 1 What is Microsoft Graph?
- 2 Use cases
- 3 Authentication and authorization
- 4 What tools do I need?
- 5 Access tokens
- 6 Lab: Interact with Microsoft Graph
- 7 Conclusion
What is Microsoft Graph?
Microsoft Graph is a REST API that enables you to interact with Microsoft 365 services and Azure Active Directory in an automated way. You can use it for simple automation tasks up to complex applications and integrations. Applications like provisioning or governance solutions usually utilise API’s like Microsoft Graph in the background aswell.
As of today, endpoints in the following categories are available:
- Users
- Groups
- Applications
- Calendars
- Change notifications
- Compliance
- Cross-device experiences
- Customer booking
- Device and app management
- Education
- Extensions
- Files
- Identity and access
- Notes
- People and workplace intelligence
- Personal contacts
- Reports
- Search
- Security
- Sites and lists
- Tasks and plans
- Teamwork and communications
- To-do tasks
- Workbooks and charts
You’ll find more details about each category in the API v1.0 reference.
Use cases
Here are some simple use cases to fuel your thoughts:
- Create/modify/delete users and groups during a joiner-mover-leaver process
- Disable user based on security incidents
- Create automated Planner tasks or lists items
- Get profile information or profile photos from an authenticated user
- Provision a Microsoft 365 Groups/Teams including specific Channels, Tabs and a welcome message
- List Planner tasks assigned to me inside other applications
- And many more
Microsoft Graph can only be used in an authenticated context. You can use the following principal types to authenticate and retrieve an access token:
- Azure AD user
- Service principal (Azure AD app registration)
- Managed Identity (system- and user assigned)
Microsoft Graph permissions
To work with Microsoft Graph, the identity you use needs permissions. There are two types of permissions:
Permission types
Delegated permissions
Delegated permissions are used in the delegated access scenario. They’re permissions that allow the application to act on behalf of a signed-in user. However, the application will never be able to access anything the signed-in user couldn’t access.
Application permissions
Application permissions are used in the app-only access scenario, without a signed-in user present. The application will be able to access any data that the permission is associated with. For example, an application granted the Files.Read.All application permission will be able to read any file in the organization.
The use case of your automation script determines the permission type you need in the end.
Granting permissions
Microsoft Graph allows you to grant fine-grained permissions to an identity object. Always keep Zero Trust in mind and only grant the permissions needed for the task.
You can find an overview of all permissions and IDs here: All permissions and IDs
Let’s assign some permissions to a service principal (App registration) via the Azure Portal:
- Sign in to the Azure Portal and navigate to the App registrations blade
- Select your app registration or create a new one (Create a service principal in Azure)
- In your app registration, open the API permissions blade
- Select Add a permission > Microsoft Graph > Application permissions
- Search for User.Read.All and select Add permissions
You might have noticed the orange warning on the right, stating that you need to grant admin consent:
Some permissions, usually ones that enable access to more or sensitive data, require consent from an administrator in order to finally be applied. You’ll get more information about the permissions by clicking on the entry. To grant admin consent, select Grant admin consent for {directoryname}.
What tools do I need?
The Microsoft Graph API provides endpoints for several tools like PowerShell or Azure CLI. When you run a PowerShell command against Azure AD, it in fact targets a Microsoft Graph API endpoint most of the time. See a PowerShell module as a wrapper for certain API endpoints, which helps you in terms of usability, authentication and automation possibilities.
Using tools like PowerShell brings the downside of dependencies, where you need to be able to install PowerShell modules wherever you run your automation. What if we can’t use PowerShell, like C# or Java? This is where simple REST calls come into play, which can be achieved in almost every language. We’ll take a look at that later in the lab.
Access tokens
An access token is a small piece of text with information about the access an identity is subjected to. To obtain an access token, you first need to authenticate against an identity provider or sometimes called secure token service (STS), like Azure AD for example. If your authentication and authorization was successful, the identity provider will hand out an access token, which you in turn hand over to the application you need to access. Access tokens are usually short-lived, like an hour, before they have to be obtained again, which is one of many countermeasures against token theft. If you would like to know more about access- and refresh tokens, take a look at What Are Refresh Tokens and How to Use Them Securely
Azure AD uses a token format called JSON Web Token, short JWT. JWT tokens exist of three parts:
- Header
- Payload
- Signature
Let’s compare it to a cinema ticket, which you first have to get at a counter (Azure AD). So you need access to a specific movie (Audience/API Endpoint) at a specific time. This ticket is then only valid for the respective movie and time in the defined room, and no other. The same principle applies when accessing an application with an access token. You obtain a token for a specific application, e.g. Microsoft Graph. You cannot access other applications like the Azure Resource Graph with the same token, you’d have to obtain another access token with the correct so called audience claim.
Lab: Interact with Microsoft Graph
Let’s say we want to know which service principals have been provisioned in our tenant in the last number of days. We ask the Graph API for all service principals from the last 30 days and create a Teams adaptive card via webhook for each record, as a kind of review task.
1. Prerequisites
Permissions
To list tenant applications and service principals, your user or service principal needs at least one of the following Graph API permissions:
- For service principals
- Application.Read.All
- Application.ReadWrite.OwnedBy
- Application.ReadWrite.All
- For users
- Any of the higher privileged Azure AD roles
Teams and webhooks
Since we’ll send information to a Teams channel using webhooks, we need to configure the webhook connector first, as described here: Create Incoming Webhooks
All files from this lab can be found in my GitHub repository.
2. Define variables
First we add some variables to simplify our script. Make sure you update lines 2 and 4 with your values:
# Variables $tenantName = "Your tenant name or id" $daysBack = "-30" $teamsWebhookUri = "Your Teams webhook URL" $graphApiVersion = "v1.0" $graphApiEndpoint = "https://graph.microsoft.com/$($graphApiVersion)"
3. Login to Azure
To access the Microsoft Graph API we need to authenticate first:
# Login to Azure az login --tenant $tenantName
4. Obtain access token and create request header
After successful login, we obtain our access token from the active Azure CLI session and construct the request header. As you’ve learned in this article, we need to send our access token alongside our GET request in the request header in order to authenticate against the API:
# Obtain access token from the authenticated Azure CLI session and define request headers $graphAccessToken = (az account get-access-token --resource=https://graph.microsoft.com | ConvertFrom-Json).accessToken $requestHeaders = @{ "Authorization" = "Bearer $($graphAccessToken)" }
5. Prepare webhook send function
In the next step we will loop through the response of our API request. So that we don’t have to declare the entire payload several times, we prepare a function that we then call in the foreach loop:
# Function to create the payload and invoke the webhook itself function Send-Webhook { param ( [string]$createdDateTime, [string]$displayName, [string]$objectId ) # JSON payload representing the Teams Adaptive Card content $payloadJson = @" { "@type": "MessageCard", "@context": "http://schema.org/extensions", "themeColor": "0076D7", "summary": "Review - New service principal found", "sections": [{ "activityTitle": "REVIEW - New service principal found: $($displayName)", "activitySubtitle": "Tenant: $($tenantName)", "facts": [{ "name": "Service principal name", "value": "$($displayName)" }, { "name": "Service principal object id", "value": "$($objectId)" }, { "name": "Creation datetime", "value": "$($createdDateTime)" }], "markdown": true }], "potentialAction": [{ "@type": "OpenUri", "name": "Open in Azure Portal", "targets": [{ "os": "default", "uri": "https://portal.azure.com/#view/Microsoft_AAD_IAM/ManagedAppMenuBlade/~/Overview/objectId/$($sp.id)/appId/$($sp.appId)/preferredSingleSignOnMode~/null" }] }] } "@ # Create Teams Adaptive Card using a post request Invoke-RestMethod -Method Post -ContentType 'Application/Json' -Body $payloadJson -Uri $teamsWebhookUri }
6. Calling the Microsoft Graph API
Now is the time to call the Microsoft Graph API and request all service principals with a creation datetime older than the last 30 days. Take a close look at line 64, where we filter results directly in URL using the filter query parameter:
# Get service principals with a creation date older than 30 days $utcDateTime = (Get-Date).AddDays($daysBack) | Get-Date -Format yyyy-MM-ddTHH:mm:ssZ $servicePrincipals = (Invoke-RestMethod -Method Get -Headers $requestHeaders -Uri "$($graphApiEndpoint)/servicePrincipals?`$filter=createdDateTime ge $utcDateTime").value
7. Invoke Teams webhooks with custom data
The last thing to do now is to loop through our response and send a Teams webhook for each record with it’s custom data:
# Invoke Teams webhooks with custom data foreach ($sp in $servicePrincipals) { Send-Webhook -displayName $sp.displayName -objectId $sp.id -createdDateTime $sp.createdDateTime }
8. Check the result in Teams
As a result, you should now see several Adaptive Cards in your Teams channel in which you configured the Webhook connector in the beginning. It should look something like this:
Conclusion
API’s like Microsoft Graph provide you with almost endless possibilities in automation or even application development. It provides data and interaction with existing services, which is especially interesting in modern work environments.
I hope this short lab gave you a good first look on how you can interact with the Microsoft Graph API in a simple way using PowerShell, without the need to know programming languages. It’s also important to know about the several key aspects involved in API’s, like tokens or general formats of REST API calls.
What daily challenges did you solve using Microsoft Graph? Let me know in the comments below, cheers!