Getting started with Graph API and PowerShell

graph

If you havent heard about Microsoft Graph API lately, you have probably been living outside of civilazation. Graph API is Microsofts master communication service that connects and handles data between almost any Azure or Microsoft 365 service in the background. If you are already used to PowerShell and modules, the toolkits you use to work with and automate your cloud environment, the chance that its all Graph API deep inside these moduels is big.

If you go here, and scroll down to Developer on the left side. Choose either v1.0 Reference or Beta reference. Here you can see what products and services you can interact with in Graph. These sites contain the URL and request you need for pulling information or update/create new objects like users or groups.

The best way to get started playing around with Graph API before starting with working on the data in PowerShell is to use the Graph Explorer. Graph Explorer is a way to interact with the Graph API in the web browser. You can construct links and requests and test them out. There are alot of example requests. Even some you can run without being logged in.

The difrent types of request you can send is GET, POST, PUT, PATCH and DELETE.
You can read more about them here.

So lets jump right into it and play with the Graph Explorer.
First we are going to just simply get a list of Groups. Sign in on the left side of the Graph Explorer. To get all groups you simply choose method GET, and enter this URL in the query field: https://graph.microsoft.com/v1.0/Groups

ge.png

Next we are going to create a new Office 365 group. We use the same URL, but set this to be a POST request as we are creating something. Take a look here to see how to construct the request body.

ge2.png

We have now learned how to both gather group info and create new groups trough the Graph Explorer.  As a little sidenote, the request boddies are constructed in JSON format.

Next we will look at how we can do the same operations with Graph by using PowerShell.

First you need a way to authenticate against Azure AD and get a access token. For production and maybe more granular security you should also create your own Azure app, but for testing purposes we will use a known PowerShell client ID.

Here you see the part that gets you a access token and lets you authenticate with Graph:

   #Parameters
$clientId = "1950a258-227b-4e31-a9cf-717495945fc2"
$redirectUri = "urn:ietf:wg:oauth:2.0:oob"
$resourceURI = "https://graph.microsoft.com"
$authority = "https://login.microsoftonline.com/common"
#Remove commenting on username and password if you want to run this without a prompt.
#$Office365Username='user@domain'
#$Office365Password='VeryStrongPassword' 
#pre requisites
try {
$AadModule = Import-Module -Name AzureAD -ErrorAction Stop -PassThru
}
catch {
throw ‘Prerequisites not installed (AzureAD PowerShell module not installed)'
}
$adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
$adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
[System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
[System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null
$authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority

##option without user interaction
if (([string]::IsNullOrEmpty($Office365Username) -eq $false) -and ([string]::IsNullOrEmpty($Office365Password) -eq $false))
{
$SecurePassword = ConvertTo-SecureString -AsPlainText $Office365Password -Force
#Build Azure AD credentials object
$AADCredential = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential" -ArgumentList $Office365Username,$SecurePassword
# Get token without login prompts.
$authResult = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authContext, $resourceURI, $clientid, $AADCredential);
}
else
{
# Get token by prompting login window.
$platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Always"
$authResult = $authContext.AcquireTokenAsync($resourceURI, $ClientID, $RedirectUri, $platformParameters)
}
$accessToken = $authResult.result.AccessToken

To query Graph and create a PowerShell variable with groups data, you run the following “code”:

$apiUrl = 'https://graph.microsoft.com/v1.0/Groups/'
$Data = Invoke-RestMethod -Headers @{Authorization = "Bearer $accessToken"} -Uri $apiUrl -Method Get
$Groups = ($Data | select-object Value).Value

We can now take a look at the content of one of the groups in the $Groups variable:

GraphPS1.png

Now we know how to create a request to get information from Graph into PowerShell. The next step is to create a POST query and learn how to construct a JSON body in PowerShell, so we can create a new group. Notice i write the $body variable in a format that is valid in PowerShell, then convert it to JSON. Arrest me if im wronge, but im no JSON expert. If there is a way to use the request body as it is in Graph Explorer right into PowerShell, please let me know.

$body = @{
description = "DemoBlogPowerShell";
displayName = "Demo Blog PowerShell";
groupTypes = @("Unified");
mailEnabled = $true;
mailNickname = "DemoBlogPowerShell";
securityEnabled = $false;
}
$bodyJSON = $body | ConvertTo-Json

$apiUrl = 'https://graph.microsoft.com/v1.0/groups'
$Data = Invoke-RestMethod -Headers @{Authorization = "Bearer $accessToken"} -Uri $apiUrl -Body $bodyJSON -Method Post -ContentType 'application/json'

Now you have learned whats needed to get a jumpstart in using Graph API, and leavraging the power in PowerShell at the same time. As Microsoft have a high focus on Graph, i think there will be a lot more products you can work with in the future trough this API.

7 thoughts on “Getting started with Graph API and PowerShell

  1. Great Post!
    For some reason it was not working like that for me, i had to make 3 minor changes:

    In the credential line I replaced this:
    $AADCredential = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential” -ArgumentList $Office365Username,$SecurePassword
    with this:
    $AADCredential = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential” -ArgumentList $Office365Username,$SecurePassword

    In the $authresult I changed this:

    $authResult = $authContext.AcquireToken($resourceURI, $clientId,$AADCredential)

    with this:
    $authResult = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authContext, $resourceURI, $clientid, $AADCredential);

    and finally this:
    $accessToken = $authResult.AccessToken

    with:
    $accessToken = $authResult.result.AccessToken

    Like

    • Thanks.

      Strange one, could it be that you have a different module version or version of PowerShell? I only tested with modern auth logon popup, not by stating username/password in the script.

      Like

      • Ok, now it works. I made some cosmetics on the assembly loading too.

        #based on https://github.com/microsoftgraph/powershell-intune-samples/blob/master/Authentication/Auth_From_File.ps1

        #Parameters
        $clientId = “1950a258-227b-4e31-a9cf-717495945fc2”
        $redirectUri = “urn:ietf:wg:oauth:2.0:oob”
        $resourceURI = “https://graph.microsoft.com”
        $authority = “https://login.microsoftonline.com/common”
        $authContext = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext” -ArgumentList $authority
        #$Office365Username=’user@domain’
        #$Office365Password=’VeryStrongPassword’

        #pre requisites
        try {

        $AadModule = Import-Module -Name AzureAD -ErrorAction Stop -PassThru

        }

        catch {

        throw ‘Prerequisites not installed (AzureAD PowerShell module not installed)’

        }
        $adal = Join-Path $AadModule.ModuleBase “Microsoft.IdentityModel.Clients.ActiveDirectory.dll”
        $adalforms = Join-Path $AadModule.ModuleBase “Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll”

        [System.Reflection.Assembly]::LoadFrom($adal) | Out-Null

        [System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null

        ##option without user interaction

        if (([string]::IsNullOrEmpty($Office365Username) -eq $false) -and ([string]::IsNullOrEmpty($Office365Password) -eq $false))
        {
        $SecurePassword = ConvertTo-SecureString -AsPlainText $Office365Password -Force
        #Build Azure AD credentials object
        $AADCredential = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential” -ArgumentList $Office365Username,$SecurePassword
        # Get token without login prompts.
        $authResult = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authContext, $resourceURI, $clientid, $AADCredential);

        }
        else
        {
        # Get token by prompting login window.
        $platformParameters = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters” -ArgumentList “Always”

        $authResult = $authContext.AcquireTokenAsync($resourceURI, $ClientID, $RedirectUri, $platformParameters)

        }

        $accessToken = $authResult.result.AccessToken

        Like

  2. That’s the issue then. I only tested it with the user and pass parameters because I needed to automate.
    The Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential is used for integrated authentication while the Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential is used for passing user and password.
    merging the changes should do the trick. I’ll look into it and let you know

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s