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
}