Functions/Get-PartnerCenterAccessToken.ps1

<#
.SYNOPSIS
    This function retrieves an access token from the Partner Center authentication servers.
.DESCRIPTION
    This function retrieves an access token from the Partner Center authentication servers.
    This access token is used in Partner Center REST API calls.
    Returns null if failed to retrieve the access token.
.EXAMPLE
    Get-PartnerCenterAccessToken -Endpoint $Endpoint
.EXAMPLE
    $Endpoint | Get-PartnerCenterAccessToken
.EXAMPLE
    Get-PartnerCenterAccessToken -Username $username -Password $password -ApplicationId $applicationId
#>

function Get-PartnerCenterAccessToken {
    [CmdletBinding(PositionalBinding=$false)]
    [OutputType([String])]
    param (
        # The username of the Partner Center admin account.
        [Parameter(Mandatory=$true, ParameterSetName="credential")]
        [String]$username,

        # The password of the Partner Center admin account.
        [Parameter(Mandatory=$true, ParameterSetName="credential")]
        [SecureString]$password,

        # The Partner Center Native App Application Id.
        [Parameter(Mandatory=$true, ParameterSetName="credential")]
        [GUID]$applicationId,

        # The MSPComplete Endpoint containing the Partner Center admin credentials.
        [Parameter(Mandatory=$true, ParameterSetName="endpoint", ValueFromPipeline=$true)]
        $endpoint
    )

    # If given endpoint, retrieve username, password and application ID
    if ($PSCmdlet.ParameterSetName -eq "endpoint") {
        $partnerCenterCredential = $endpoint.Credential
        $username = $partnerCenterCredential.Username
        $password = $partnerCenterCredential.Password

        # Check if endpoint has application ID extended property
        if (!($endpoint.ExtendedProperties) -or !(Search-HashTable -HashTable $endpoint.ExtendedProperties -Key "ApplicationId")) {
            Write-Error "Endpoint provided does not have an 'ApplicationId' extended property."
            return $null
        }
        $applicationId = $endpoint.ExtendedProperties.ApplicationId
    }

    # Retrieve plaintext password
    $plainTextPassword = ([PSCredential]::new("username", $password)).GetNetworkCredential().Password

    # Extract the domain from the username
    $domain = Get-EmailAddressDomain $username
    if ([String]::IsNullOrWhiteSpace($domain)) {
        Write-Error "Failed to extract domain from username '$($username)'."
        return $null
    }

    # Construct the REST call
    Add-Type -AssemblyName System.Web
    $url = "https://login.windows.net/$($domain)/oauth2/token"
    $body = "grant_type=password&resource=https://api.partnercenter.microsoft.com&" `
          + "client_id=$([System.Web.HttpUtility]::UrlEncode($applicationID))&" `
          + "username=$([System.Web.HttpUtility]::UrlEncode($username))&" `
          + "password=$([System.Web.HttpUtility]::UrlEncode($plainTextPassword))&" `
          + "scope=openid"

    # 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 $null
    }

    # 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 $null
    }

    # Return the access token
    return $response.access_token
}