PowerShell access to the Graph API

If you’ve been living under a rock in the Office 365 world recently, you may not have heard about the Microsoft Graph. (“One Endpoint to rule them all“). But if you haven’t been under a rock then you’ll know that Microsoft is intending to surface all of the various REST endpoints that currently exist on different URLs and schemas today, via a single unified URL of graph.microsoft.com.

What this basically means is that where in the past you’ve had to get User information from your SharePoint Tenant UPA REST endpoint, and then the users picture from the Exchange endpoint, you’ll now (well over time) do it all from a single endpoint.

Access to this unified endpoint is of course well protected by oAuth authentication and there are a few hoops that you need to jump through in order to get your application (in whatever form it takes) to talk to the graph. One of the things that I wanted to do was to create a PowerShell harness that allows me to make calls into the graph for my Tenant to do some basic data extraction.

As I wasn’t able to find any clear code on how to do this anywhere on the net I decided to put this Post together to help anyone in the same boat. The rest of this post will take you through this process so that you can better understand App authentication and authorization against the Graph APIs.

The first thing that we need to do is to tell Azure Active Directory that we’re writing an application (or rather a PoSH script) that will access the graph. We’ll then use this application definition to align the permissions that tell Azure what information the script is allowed to access.

To do this for your tenant, log on to https://portal.azure.com and sign in with a global admin account. Then select Azure Active Directory from the left hand navigation. Once the AAD blade is open, select App registrations.

Creating a new app registration to access the graph api

Click +Add and then give your application a name, choose the Web app /API Application type (NB! Do not choose Native Client, else you cannot select App-Only permissions!), and finally provide a made up logon URL.

Provide app information for the graph api

Once completed you should see a new application in your Azure AAD dashboard.

The created graph api App

Click on this entry to open up the settings window. The first thing you need to do now is to capture the Application ID shown on the settings page. We’re going to use this to identify the application in PowerShell shortly, so cut and paste it into notepad.

The all important graph api app ID

Now in the right hand blade menu, select Keys. Add a description and set the duration to 2 Years. (Be warned it looks like the Graph API does NOT permit a Never Expires secret and you just receive Invalid Secret during the script, so make sure you pick 1 or 2 years expiry!).

Once you click Save, the new Secret key will be revealed!

Creating the APP Secret

Note the warning when you save, this Secret is shown to you once and once only! So cut and paste it into Notepad along with your AppID now!

Don't forget to copy it!

Close that blade, then the last thing we need to do is assign the permissions that this client application will need. You can do this by clicking on the Required Permissions option.

Add the Graph api permissions

By default you’ll have a single Windows Azure Active Directory permission selected, so click +Add at the top of this window, then choose “Select an API” in the column that pops up to the right and choose Microsoft Graph.

Selecting the Microsoft graph api

Once you click select at the bottom, the permissions window will pop up, allowing you to select which permissions the application should be allowed to have. In my case I want to be able to retrieve a list of Users and a List of Groups, so I’ll select “Read all Groups” and “Read all users’ full profiles”. Then hit Select.

NB: Thanks to my colleague James Brennan, he highlighted a missing permission in this step. If you want to return a full list of users, you also need the “Read all users full profile” delegated permission on the Windows Azure Active Directory permission.

Selecting the individual graph api permission req

Click “Done” to close the “Add API access” blade and you should now see the Microsoft Graph listed with a number of Application permissions. It’s important to understand that at this point, you have only requested the permissions that the app needs. If this were a client app, the User would have to consent to these permissions before you could do anything. In this case, we’re using App only permissions, so the Admin must consent by clicking on Grant Permissions link.

Don't forget admin consent!

This will pop up a small dialog asking you to confirm that the app should be granted the permissions requested. Once done a notification will popup to show that permissions were granted. NB If you come back to amend the permissions at any time, you MUST remember to provide admin consent after every change, otherwise you’ll receive authentication errors. (And don’t forget to also do this for the Windows Azure AD permission too if you’ve made the change in bold above!)

The last thing we need is the Endpoint URL that we will use to obtain the Authorisation Token. This URL is specific to your tenant as it includes your Tenant ID. To obtain this URL, go pack to the App registrations screen and select Endpoints from the top of the window.

Finally we need out oAuth endpoint for the graph api!

This will display a list of Endpoints that you can use. You want the value from the OAUTH 2.0 TOKEN ENDPOINT which should start https://login.windows.net. With this secured safely with the App ID and App Secret, we can now close the Azure console and continue with the PowerShell bit.

Armed with the App Id, App Secret and the Tenant Endpoint, we can now make a very simple PowerShell script that will connect to the Graph Endpoint and request a list of Groups in the tenant.


The code is fairly self-explanatory and should hopefully provide a good starting point for anyone like me that is starting to look at what can be done with PowerShell and the Office Graph. Just be warned this code is far from perfect as it doesn’t handle the Bearer Token expiry or anything like that!

Have fun!



Skip to comment form

    • Jurgen on Thu 26 Oct 17 at 6:21 am
    • Reply

    I had to UrlEncode the $appSecret to make this work.

    Add-Type -AssemblyName System.Web

    # Encode ClientSecret
    $clientSecretEncoded = [System.Web.HttpUtility]::UrlEncode($appSecret)

    1. Thanks Jurgen,

      I obviously got lucky with my app secret and it contained straight forward characters.

      I’ll get the script updated asap.


        • Jurgen on Thu 26 Oct 17 at 7:41 am
        • Reply

        Other than that it was a great example/blog post. Thank you for posting it.

  1. Excellent. I do not know how you managed to work this out, i searched the internet for hours for a powershell solution to this.

    1. Persistence mostly! – It’s a lot easier now with PNP PowerShell as you can use the Connect-PNPOnline with the -Scopes option which allows you to specify the permissions your connection needs. You then use the Get-PNPAccessToken to get the token for use in your Invoke-RestMethod.

      This method is still a good one though if you’re using the script for automation, as you can use the client credentials method to save having the manual interaction part of the permissions and credentials.

Leave a Reply

Your email address will not be published.


This site uses Akismet to reduce spam. Learn how your comment data is processed.