msGraphFunctions.ps1

<#
.COPYRIGHT
Portions of this are derived from Microsoft content on GitHub at the following URL:
 
https://github.com/microsoftgraph/powershell-intune-samples/blob/master/ManagedDevices/ManagedDevices_Apps_Get.ps1
 
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
See LICENSE in the project root for license information.
#>


#region Microsoft GitHub sample code

#$graphApiVersion = "beta"

function get-AuthToken {
    <#
    .SYNOPSIS
        This function is used to authenticate with the Graph API REST interface
    .DESCRIPTION
        The function authenticate with the Graph API Interface with the tenant name
    .PARAMETER User
        UserName for cloud services access
    .EXAMPLE
        Get-AuthToken -User "john.doe@contoso.com"
 
        Authenticates user with the Graph API interface
    .NOTES
        NAME: Get-AuthToken
    #>

    [cmdletbinding()]
    param (
        [parameter(Mandatory)] $User
    )

    $userUpn = New-Object "System.Net.Mail.MailAddress" -ArgumentList $User
    $tenant = $userUpn.Host

    Write-Host "Checking for AzureAD module..."
    $AadModule = Get-Module -Name "AzureAD" -ListAvailable

    if ($null -eq $AadModule) {
        Write-Host "AzureAD PowerShell module not found, looking for AzureADPreview"
        $AadModule = Get-Module -Name "AzureADPreview" -ListAvailable
    }

    if ($null -eq $AadModule) {
        Write-Host
        Write-Host "AzureAD Powershell module not installed..." -f Red
        Write-Host "Install by running 'Install-Module AzureAD' or 'Install-Module AzureADPreview' from an elevated PowerShell prompt" -f Yellow
        Write-Host "Script can't continue..." -f Red
        Write-Host
        exit
    }
    # Getting path to ActiveDirectory Assemblies
    # If the module count is greater than 1 find the latest version
    if ($AadModule.count -gt 1){
        $Latest_Version = ($AadModule | Select-Object version | Sort-Object)[-1]
        $aadModule = $AadModule | Where-Object { $_.version -eq $Latest_Version.version }
        # Checking if there are multiple versions of the same module found
        if($AadModule.count -gt 1){
            $aadModule = $AadModule | Select-Object -Unique
        }
        $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
        $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
    }
    else {
        $adal = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
        $adalforms = Join-Path $AadModule.ModuleBase "Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll"
    }

    Write-Verbose "preparing authentication request session"
    [System.Reflection.Assembly]::LoadFrom($adal) | Out-Null
    [System.Reflection.Assembly]::LoadFrom($adalforms) | Out-Null

    $clientId = "d1ddf0e4-d672-4dae-b554-9d5bdfd93547"
    $redirectUri = "urn:ietf:wg:oauth:2.0:oob"
    $resourceAppIdURI = "https://graph.microsoft.com"
    $authority = "https://login.microsoftonline.com/$Tenant"
    
    try {
        Write-Verbose "connecting to $authority"
        $authContext = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext" -ArgumentList $authority
        # https://msdn.microsoft.com/en-us/library/azure/microsoft.identitymodel.clients.activedirectory.promptbehavior.aspx
        # Change the prompt behaviour to force credentials each time: Auto, Always, Never, RefreshSession
        $platformParameters = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformParameters" -ArgumentList "Auto"
        $userId = New-Object "Microsoft.IdentityModel.Clients.ActiveDirectory.UserIdentifier" -ArgumentList ($User, "OptionalDisplayableId")
        Write-Verbose "1. $resourceAppIdURI"
        Write-Verbose "2. $clientId"
        Write-Verbose "3. $redirectUri" 
        Write-Verbose "4. $platformParameters"
        Write-Verbose "5. $userId"
        $authResult = $authContext.AcquireTokenAsync($resourceAppIdURI,$clientId,$redirectUri,$platformParameters,$userId).Result

        # If the accesstoken is valid then create the authentication header
        if ($authResult.AccessToken){
            # Creating header for Authorization token
            $authHeader = @{
                'Content-Type'='application/json'
                'Authorization'="Bearer " + $authResult.AccessToken
                'ExpiresOn'=$authResult.ExpiresOn
            }
            return $authHeader
        }
        else {
            Write-Host "Authorization Access Token is null, please re-run authentication..." -ForegroundColor Red
            break
        }
    }
    catch {
        Write-Error $_.Exception.Message
        Write-Error $_.Exception.ItemName
        break
    }
}

function get-psIntuneAuth {
    <#
    .SYNOPSIS
        Returns authentication token object
    .PARAMETER UserName
        UserName for cloud services access
    .EXAMPLE
        Get-psIntuneAuth -UserName "john.doe@contoso.com"
    .NOTES
        Name: Get-psIntuneAuth
    #>

    [CmdletBinding()]
    param (
        [parameter(Mandatory)][string] $UserName
    )
    # Checking if authToken exists before running authentication
    if ($global:authToken) {

        # Setting DateTime to Universal time to work in all timezones
        $DateTime = (Get-Date).ToUniversalTime()

        # If the authToken exists checking when it expires
        $TokenExpires = ($authToken.ExpiresOn.datetime - $DateTime).Minutes

        if ($TokenExpires -le 0){
            Write-Host "Authentication Token expired" $TokenExpires "minutes ago" -ForegroundColor Yellow
            # Defining Azure AD tenant name, this is the name of your Azure Active Directory (do not use the verified domain name)
            $global:authToken = Get-AuthToken -User $UserName
        }
    }
    else {
        # Authentication doesn't exist, calling Get-AuthToken function
        $global:authToken = Get-AuthToken -User $UserName
    }
}

function get-MsGraphData($Path) {
    <#
    .SYNOPSIS
        Returns MS Graph data from (beta) REST API query
    .PARAMETER Path
        REST API URI path suffix
    .NOTES
        This function was derived from https://www.dowst.dev/search-intune-for-devices-with-application-installed/
        (Thanks to Matt Dowst)
    #>

    $FullUri = "https://graph.microsoft.com/$graphApiVersion/$Path"
    [System.Collections.Generic.List[PSObject]]$Collection = @()
    $NextLink = $FullUri
    do {
        $Result = Invoke-RestMethod -Method Get -Uri $NextLink -Headers $AuthHeader
        if ($Result.'@odata.count') {
            $Result.value | ForEach-Object{$Collection.Add($_)}
        } 
        else {
            $Collection.Add($Result)
        }
        $NextLink = $Result.'@odata.nextLink'
    } while ($NextLink)
    return $Collection
}


#endregion