Functions/Get-MicrosoftGraphAuthenticationToken.ps1

<#
.SYNOPSIS
    This function contacts the Microsoft Graph authentication servers to obtain an authentication token.
#>

function Get-MicrosoftGraphAuthenticationToken {
    [CmdletBinding(PositionalBinding=$false)]
    [OutputType([String])]
    param (
        # The application ID of the Microsoft Graph web application.
        [Parameter(Mandatory=$true, ParameterSetName="values")]
        [ValidateNotNullOrEmpty()]
        [String]$applicationId,

        # The client secret of the Microsoft Graph web application.
        [Parameter(Mandatory=$true, ParameterSetName="values")]
        [ValidateNotNullOrEmpty()]
        [String]$clientSecret,

        # The name of the organization in Office 365.
        # Example: if the onmicrosoft domain is contoso.onmicrosoft.com, the organization name is 'contoso'
        [Parameter(Mandatory=$true, ParameterSetName="values")]
        [ValidateNotNullOrEmpty()]
        [String]$organizationName,

        # The MSPComplete endpoint containing the application ID and client secret in the credential.
        [Parameter(Mandatory=$true, ParameterSetName="endpoint", ValueFromPipeline=$true)]
        [ValidateNotNull()]
        $endpoint
    )

    # Retrieve the properties from the endpoint
    if ($PSCmdlet.ParameterSetName -eq "endpoint") {
        $applicationId = $endpoint.Credential.Username
        $clientSecret = $endpoint.Credential.GetNetworkCredential().Password
        if ([String]::IsNullOrWhiteSpace((Search-HashTable $endpoint.ExtendedProperties "OrganizationName"))) {
            Write-Error "The endpoint does not have an 'OrganizationName' extended property."
            return
        }
        $organizationName = $endpoint.ExtendedProperties.OrganizationName
    }

    # Construct the REST call
    $url = "https://login.microsoftonline.com/$($organizationName).onmicrosoft.com/oauth2/v2.0/token"
    $body = @{
        client_id       = $applicationId
        grant_type      = "client_credentials"
        client_secret   = $clientSecret
        scope           = "https://graph.microsoft.com/.default"
    }

    # Create hash table for params
    $invokeRestMethodParams = @{
        Uri         = $url
        ContentType = "application/x-www-form-urlencoded"
        Body        = $body
        Method      = "POST"
    }

    # Invoke the REST call
    try {
        $response = Invoke-RestMethod @invokeRestMethodParams
    }
    catch {
        Write-Error "Exception occurred while invoking REST call.`r`n$($_.Exception.Message)"
        return
    }

    # Verify the response
    if ($null -eq $response -or $response.expires_in -le 0 -or [String]::IsNullOrWhiteSpace($response.access_token)) {
        Write-Error "Failed to retrieve the access token."
        return
    }

    # Return the access token
    return $response.access_token
}