Connecting to Microsoft Graph with PowerShell

Nowadays, I find myself self-working with PowerShell almost as much as with Power Platform. Not even mention that I used to work as a software developer in the web stack world, like jQuery, and React. I remember that my first large PowerShell project was related to SharePoint 2013 site provisioning years ago. Back then PnP PowerShell library was only a dream I had to write the modules and extension our self. Today, I’m a big fan of PnP PowerShell, and I’m using it almost daily. And we should not forget those multiple other PowerShell modules available to different services of Office 365.

Of course, there are situations and times when there isn’t a built-in command available for the needed task. In many cases, you can use CSOM capabilities to close the cap (I’ll come back to this in the upcoming posts). And then there’s Microsoft Graph you can use to do a lot of things. To get us rolling, we need to authenticate against it to get AccessToken we need to use in HTTP calls against the Graph API. Here are three different scenarios on how to get the AccessToken with PowerShell.

You find all the scripts from my GitHub: https://github.com/MikkoKoskinen/SP-Poweshell/tree/master/ConnectToGraph

General Variable

The first thing you need is to register the application and set the necessary permissions for the service you won’t use. Here are the steps on how to do it: https://docs.microsoft.com/en-us/graph/auth-register-app-v2. Remember to copy the application ID and secret because we need those in the scripts.

In all the scripts below, we will need several information from the tenant and the registered application. Most importantly, we need the application id, tenant id, and the created secret id. With these, we can design and application-level connection to the Graph. For delegated permission, we will also need the credentials of the users that we want to use for the connection.

#*** Initialize variables
Write-Host "Initialize variables"
Write-Host " "

[string]$graphApp_AppId = "APPLICATION_ID"
[string]$graphApp_AppSecret = "APPLICATION_SECRET"
[string]$tenantId="TENANT_ID"
[string]$spAdminURL = "SPADMIN_URL"
[string]$graphVer = "v1.0"

#Credetential iformation to be used in delegated connections
[string]$username = "USERNAME"
[string]$password = "PASSWORD"

Connection with Application Permissions

In my example script, the needed variables are given as plain text in the script file, but for production, you might want to consider other options, like using Credential Manager or Azure Key Vault, to hide this information. At least, don’t take a straight copy from my script, add the information, and post that to some public source.

To connect against Graph with application permission we will need to build a JSON variable with application id and secret. We also need to pass a grant type of ‘client_credentials’ and scope with a value of ‘https://graph.microsoft.com/.default’.

try{

    #Connecting with Application Permissions
    Write-Host " "
    Write-Host "Connecting with Application Permissions"

    $body=@{
        client_id=$graphApp_AppId
        client_secret=$graphApp_AppSecret
        scope="https://graph.microsoft.com/.default"
        grant_type="client_credentials"
    }

    $response = Invoke-WebRequest -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body -Method Post

    $accessToken=$response.content | ConvertFrom-Json
    $AppAccessToken = $accessToken.access_token
	
	if($AppAccessToken){
		Write-Host ("...got AppAccessToken")
	}
	else{
		Write-Error -Message$ "Application access error" -Category AuthenticationError
	}
}
catch {
    $ErrorMessage = $_.Exception.Message
    Write-Host "**ERROR: Connecting with Application Permissions"
    Write-Error -Message $ErrorMessage
}

This JSON in then send with Invoke-WebRequest Post against the login API. If succeeded, we should get a JSON response back and we can parse the authentication token from it.

Connection with Delegated Permissions

A delegated connection can be done in almost similar way than the connection with application permission. Again we need the Json variable with application id and secret. Then we need to add the username and password for the user account we want to use in the connection. This time the grant type for the call is ‘password’.

try{
    #Connecting with Delegated permissions
    Write-Host " "
    Write-Host "Connecting with Delegated permissions"

    $body=@{
        client_id=$graphApp_AppId
        password= $password
        username= $username
        client_secret=$graphApp_AppSecret
        grant_type="password"
        scope="https://graph.microsoft.com/.default"
    }
$response = Invoke-WebRequest -Uri "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body -Method Post

    $accessToken=$response.content | ConvertFrom-Json
    $UserAccessToken = $accessToken.access_token
	
	if($UserAccessToken){
		Write-Host ("...got UserAccessToken")
	}
	else{
		Write-Error -Message$ "Delegated access error" -Category AuthenticationError
	}
}
catch {
    $ErrorMessage = $_.Exception.Message
    Write-Host "**ERROR: Connecting with Delegated permissions"
    Write-Error -Message $ErrorMessage
}

Again, if everything goes as planned, we should get the access code as a return value.

Connection with PnP PowerShell

For the application connect there’s also a shorter version available through PnP PowerShell module. We can call the Connect-PnPOnline function with application id and secret and get the access token with Get-PnPAccessToken call after that.

try{
    #Connecting with PnP PowerShell
    Write-Host " "
    Write-Host "Connecting with PnP PowerShell"

    Connect-PnPOnline -Url $spAdminURL -AppId $graphApp_AppId -AppSecret $graphApp_AppSecret
    $pnpAccessToken = Get-PnPAccessToken

	if($pnpAccessToken){
		Write-Host ("...got pnpAccessToken")
	}
	else{
		Write-Error -Message$ "PnP PowerShell access error" -Category AuthenticationError
	}
}
catch {
    $ErrorMessage = $_.Exception.Message
    Write-Host "**ERROR: Connecting with Delegated permissions"
    Write-Error -Message $ErrorMessage
}

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

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

%d bloggers like this: