Connecting Azure Active Directory Graph API with PowerShell using ADAL


So you need to manage Office365 through PowerShell. You can follow the Microsoft Instructions:
Install Microsoft Online Services Sign-In Assistant for IT Professionals RTW and then install AdministrationConfig-V1.1.166.0-GA.msi. After that you are OK to use Connect-MsolService and do what you need to do.
But what if you are developing a tool for a lot of people. I really didn’t want to require that much prerequisite software installations just for a simple tool. What I ended up doing is using Azure Active Directory Graph API to do what I needed to do in Office365.
To achieve that I used Microsoft.ADAL.PowerShell which is a PowerShell wrapper for Azure Active Directory Authentication Library (ADAL). I use it to get an Access Token for Azure Active Directory Graph API. After that I use Invoke-RestMethod to do my Office365 actions. I also needed to implement Paged Requests using a Skip Token for when the returned objects are above 999. For more info on that, see here.
For this example I just get all Users from a given tenant. To see what else you can do with Azure AD Graph, you can visit the Graph Explorer.
You need to put the Microsoft.ADAL.PowerShell dependencies in the script directory. They are going to be imported during script execution.
There are 3 parameters – username, password and tenant. Here is an example:
."C:\PATHTOSCRIPT\Connect_AAD_Graph.ps1" -userName "username@tennant.com" -passWord "password" -tenant "tenant.com"

Here is the PS code. Don’t forget that you need the dependency Microsoft.ADAL.PowerShell in the same directory as the script.
You can download the full script neatly packaged with its dependencies here.

Param([Parameter(Mandatory=$true)] [string]$userName,[Parameter(Mandatory=$true)] [string]$passWord,[Parameter(Mandatory=$true)] [string]$tenant)

################################################
## Start
################################################
####Check PowerShell version
$psVersion = $PSVersionTable.PSVersion

if($psVersion.Major -lt 3){
    Add-Type –AssemblyName System.Windows.Forms
    $message = @"
Your System is not meeting the system requirements.
PowerShell Version not sufficient.
Try installing .Net Framework 4.5 and Windows Management Framework 5.0.
"@
    [System.Windows.Forms.MessageBox]::Show($message , "Information")
    exit
}

####Getting script location
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath

################################################
## Import Modules
################################################
if(!(Get-Module -ListAvailable Microsoft.ADAL.PowerShell)){
    try{
        import-module "$dir\Microsoft.ADAL.PowerShell" -ErrorAction Stop
    } catch {
        write-host $_.Exception.Message -ForegroundColor Red
        Break
    }
}

################################################
## Functions
################################################

####Connect to SPO and MSOL
function connectServices($user, $pass, $tenantName){
    $phase1Success=$true
    ####Create Credentials
    $cred = New-Object System.Management.Automation.PsCredential($user, (ConvertTo-SecureString $pass -AsPlainText -Force))
   
    ####Get Token. Client ID is well known ID for Azure PowerShell
    write-host "Getting ADAL Token for MSO" -ForegroundColor Cyan
    try {
        $global:GraphToken = Get-ADALAccessToken -AuthorityName $TenantName -ClientId 1950a258-227b-4e31-a9cf-717495945fc2 -ResourceId "https://graph.windows.net" -UserName $user -Password $pass      
    } catch {
        write-host $_.Exception.Message -ForegroundColor Red
        $phase1Success=$false
    }
    return $phase1Success   
}

####Get Users in MSO
function getUsersMSO($tenant){
    $phase2Success=$true

    $body = @{
       "Content-Type"="application\json";
       Authorization="Bearer $global:GraphToken";
    }

    $global:UsersMSO=@()

    try{
        getPagedResults -tenantName $tenant
    } catch {
        write-host $_.Exception.Message -ForegroundColor Red
        $phase2Success = $false
    }

    return $phase2Success
}

####Get Results from Azure AD Graph. Supports Paged Results. Gets called by function getUsersMSO.
function getPagedResults($skipToken, $tenantName){
    if(!($skipToken)){
        write-host "Getting MSO Users. First Request." -ForegroundColor Green
        $uriConstruct = 'https://graph.windows.net/'+ $tenantName +'/users?$orderby=displayName&$top=500&api-version=1.6'

        $pagedPage = Invoke-RestMethod -Uri $uriConstruct -Headers $body -Method Get
        $global:UsersMSO += $pagedPage | Select-Object -ExpandProperty Value

        $skipToken = ($pagedPage.("odata.nextlink") -split "skiptoken=")[1]
       
        if($skipToken){
            getPagedResults -skipToken $skipToken -tenantName $tenantName
        }
    } else {
        write-host "Getting MSO Users. Paged Request" -ForegroundColor Green
        $uriConstruct = 'https://graph.windows.net/'+$tenantName+'/users?$orderby=displayName&$top=500&api-version=1.6&$skiptoken=' + $skipToken

        $pagedPage = Invoke-RestMethod -Uri $uriConstruct -Headers $body -Method Get
        $global:UsersMSO += $pagedPage | Select-Object -ExpandProperty Value

        $skipToken = ($pagedPage.("odata.nextlink") -split "skiptoken=")[1]
        if($skipToken){
            getPagedResults -skipToken $skipToken -tenantName $tenantName
        }
    }
}


################################################
## Core
################################################
$connectServices = connectServices -user $userName -pass $passWord -tenantName $tenant

if ($connectServices -eq $true){
    $status = getUsersMSO -tenant $tenant
}

$global:UsersMSO | out-gridview 

Comments