Setting up an Azure AD application within your tenant will help you in putting scripts together using Microsoft Graph that does not need any user intervention. You can apply granular permissions to the app so that the script is not able to query any other workloads or entities. This is especially important when you work in large organizations as there are dedicated teams for each of the M365 services and they are not going to give you access to query their services without a valid reason.
Please check the first two articles about how to install & work with MS Graph SDK & work with Graph Explorer if you haven’t already.
Table of Contents
How To Setup The Azure AD App?
In order to setup the application that will be used to query Microsoft Graph (for scripts, automation tasks etc), navigate to Azure Active Directory portal -> App Registrations. We will be using the OAuth 2.0 Client Credential Flow, as there will be no user interaction.
Click on ‘New Registration’.
Give a name for the application. Make it descriptive, so that it is easy for any of your colleagues to figure out what it does and why it was created. I will name mine as ‘Graph Script App’. Leave the supported account type as ‘Accounts in this organizational directory only’.
In the ‘Redirect URI’, select ‘web’ as the platform and ‘https://localhost’ as the url & click the ‘Register’ button.
The application gets created in a few seconds.
Configuring The Graph Script App
There are two more steps we need to complete to use this application within our scripts. First piece of information that we need is the Application ID & Tenant ID. This is listed in the ‘overview’ tab of the app. Copy & paste it into your script editor.
We now need to create a client secret for the application. Think of it as a password where the username is the application ID. Navigate to the ‘Certificates & Secrets’ tab and click on ‘New Client Secret’.
Enter a description for the secret and an expiry period & click the ‘Add’ button.
Before you move away from the tab, copy the ‘value’ field into your script editor. If you did move away, you can delete the secret that you had created and setup a new one.
Next we need to navigate to the ‘API Permissions’ tab & configure the permissions depending on what resources we are querying in our script. Let us assume that we need to query all the users within the tenant. In order to give the app the permissions to query all users, click on ‘Add a permission’ button -> select Microsoft Graph -> Application Permissions’ and search for user.read.
Select ‘User.Read.All’ permission and click on the ‘Add permissions’ button.
If you want to write information to the user accounts, you need to select ‘User.ReadWrite.All’ permissions. If you need to play with device info, you should search for device and select ‘Device.Read.All’ or ‘Device.ReadWrite.All’ permission and add it. You get the idea! You can add multiple permissions from various services into the app in one go, if needed.
As there will not be any user intervention to accept the consent, we will have to grant the consent as an administrator by clicking on the ‘Grant admin consent’ button after adding all the required permissions.
Make sure that there is a green tick against all the permissions.
This completes the application setup in Azure AD for scripting purposes.
How To Create A Simple Script Using MS Graph?
Let’s try to create a basic script which will list all the users in the tenant and all the properties. We have set the variables & commands we need to get to a point where we can query the endpoint “https://graph.microsoft.com/v1.0/users”.
First, we need the client ID, secret, redirect uri & tenant name/id (to make it a generalized script). Let’s store all of those in a few variables as below.
Next piece is the token endpoint. We can get all the endpoints from the application’s overview tab -> Endpoints. Copy the token endpoint and paste it in the script. You can change the tenant id from the url and add the tenant id variable to generalize it if required.
We now need to create a splat with all the info we have for the client credentials flow, so the grant type will be client_credentials, the scope will be the graph endpoint (the ./default brings all the permissions assigned), client id & secret which we have stored safely.
Next, we use these info which is stored in $body and post it to the token endpoint to get an access token back. We use the Invoke-RestMethod command to achieve this.
$tokenreply = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenant_id/oauth2/v2.0/token" -Method Post -Body $body
We will have the access token stored in the $tokenreply variable now. The token type is ‘Bearer’ and it also has the expiry information. You can use $tokenreply.access_token if you want to get your hands on the token.
If you want to decode the token and see what it holds, open up https://jwt.ms/ & paste the token. The decoded token will show you the permissions assigned, the app in use, the tenant id, the API endpoint etc among many other things.
Finally we need to query graph endpoint for all the users in our tenant (which is our example use case). For that, let’s store the endpoint in a variable. say $graphendpoint = “https://graph.microsoft.com/beta/users” (beta API version gives more info than v1.0)
Next, we need to present the authorization headers which contains the access token to MS Graph using the Invoke-RestMethod. Run the command below to get past the authorization layer.
$Output = Invoke-RestMethod -Headers @{Authorization = "Bearer $($tokenreply.access_token)"} -Uri $graphendpoint -Method Get
The $Output.Value has all the information about my users.
You can select the output you need and also export it to json, csv etc as you would do in PowerShell.
$Output.value | select userprincipalname, mail, displayname, usertype | export-csv .\Users.csv
This is a basic script which explains how to connect to MS Graph and get output using the client credential flow with the help of an Azure AD application. I am sure you can expand the script from here.
I have pasted what we have worked on so far below, so that you can copy & modify it the way you see fit.
$client_id = "client id"
$client_secret = "client secret"
$tenant_id = "tenant id"
$Body = @{
grant_type = "client_credentials"
scope = "https://graph.microsoft.com/.default"
client_id = $client_id
client_secret = $client_secret
}
$tokenreply = Invoke-RestMethod -Uri "https://login.microsoftonline.com/$tenant_id/oauth2/v2.0/token" -Method Post -Body $Body
#Access token
$tokenreply.access_token
$graphendpoint = "https://graph.microsoft.com/beta/users"
$Output = Invoke-RestMethod -Headers @{Authorization = "Bearer $($tokenreply.access_token)"} -Uri $graphendpoint -Method Get
$Output.value
$Output.value | select userprincipalname, mail, displayname, usertype | export-csv .\Users.csv
Do let me know if you have any questions in the comment section.