Search code examples
azurepowershellazure-active-directoryazure-powershellmicrosoft-partner-center

invalid_grant error - PowerShell Azure PartnerCenter Get-PartnerCustomer API call


I am trying to write a script in PowerShell ISE (5.1) that retrieves all customers using the PartnerCenter Powershell. My script is:

type here# Azure AD Application Configuration
$tenantId = "HIDDEN"
$appId = "HIDDEN"
$appSecret = "HIDDEN"

# Partner Center API Configuration
$scope = "https://api.partnercenter.microsoft.com/.default"

$body = @{
    grant_type    = "client_credentials"
    scope         = $scope
    client_id     = $appId
    client_secret = $appSecret
    resource      = "https://api.partnercenter.microsoft.com"
}

$params = @{
    ContentType = "application/x-www-form-urlencoded"
    Headers     = @{ "Content-Type" = "application/x-www-form-urlencoded" }
    Body        = $body
    Method      = "Post"
    URI         = "https://login.microsoftonline.com/$tenantId/oauth2/token"
}

$response = Invoke-RestMethod @params

$token = $response.access_token

Connect-PartnerCenter -AccessToken $token

# Get all customers
$customers = Get-PartnerCustomer
$customers

However, running this gives the following error:

Get-PartnerCustomer :  (invalid_grant)
At line:32 char:14
+ $customers = Get-PartnerCustomer
+              ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : CloseError: (:) [Get-PartnerCustomer], PartnerException
    + FullyQualifiedErrorId : Microsoft.Store.PartnerCenter.PowerShell.Commands.GetPartnerCustomer

In the Azure Portal, the app is registered properly, I am sure the tenantid, appid and appsecret are correct and the following API permissions are added so that should be sufficient (and approved by admin):

Added API permissions

The problem is probably MFA. This can also be seen by running the following script:

# Azure AD Application Configuration
$tenantId = "HIDDEN"
$appId = "HIDDEN"
$appSecret = "HIDDEN"

# Connect to Partner Center using the access token
Connect-PartnerCenter

# Get Customers
$customers = Get-PartnerCustomer

# Display Customers
$customers

In this case, chrome opens, asks for login and afterwards MFA is requested. Doing this manually works and the customers are succesfully outputted as a result. However I would like the script to connect automatically using the API keys without needing to login manually, and this invalid_grant error is probably caused due to the MFA.

Is there a simple way to fix this? Since it should be an easy script and I know this was possible in the past, before MFA was required, but now I just can't get it to work. Keep getting the invalid_grant error Or is there maybe an alternative way to do this?


Solution

  • I created one app registration and added API permissions as below:

    enter image description here

    When I ran your script in my environment, I too got same error like this:

    $tenantId = "HIDDEN"
    $appId = "HIDDEN"
    $appSecret = "HIDDEN"
    
    # Partner Center API Configuration
    $scope = "https://api.partnercenter.microsoft.com/.default"
    
    $body = @{
        grant_type    = "client_credentials"
        scope         = $scope
        client_id     = $appId
        client_secret = $appSecret
        resource      = "https://api.partnercenter.microsoft.com"
    }
    
    $params = @{
        ContentType = "application/x-www-form-urlencoded"
        Headers     = @{ "Content-Type" = "application/x-www-form-urlencoded" }
        Body        = $body
        Method      = "Post"
        URI         = "https://login.microsoftonline.com/$tenantId/oauth2/token"
    }
    
    $response = Invoke-RestMethod @params
    
    $token = $response.access_token
    
    Connect-PartnerCenter -AccessToken $token
    
    # Get all customers
    $customers = Get-PartnerCustomer
    $customers
    

    Response:

    enter image description here

    In the cases where MFA is enabled, you can make use of refresh tokens that will be valid for 90 days as an alternative.

    To get refresh token, you need to login with Partner Center user account manually once and can use it to generate access tokens.

    I used below PowerShell script that gives refresh token in response after successful authentication.

    $appId = "appId"
    $appSecret = ConvertTo-SecureString -String "secret" -AsPlainText -Force
    $tenantId = "tenantId" 
    $credential = [PSCredential]::new($appId, $appSecret)
    
    $tokenSplat = @{
        ApplicationId        = $appId
        Credential           = $credential
        Scopes               = "https://api.partnercenter.microsoft.com/user_impersonation"
        ServicePrincipal     = $true
        TenantId             = $tenantId
        UseAuthorizationCode = $true
    }
    
    $token = New-PartnerAccessToken @tokenSplat
    
    $token.RefreshToken
    

    Response:

    enter image description here

    You can now use this refresh token that is valid for 90 days and connect to Partner Center like this:

    $connectSplat = @{
        ApplicationId = $appId
        Credential    = $credential
        RefreshToken  = $token.RefreshToken
    }
    
    Connect-PartnerCenter @connectSplat
    
    Get-PartnerRole
    

    Response:

    enter image description here

    Reference: Generate Microsoft Partner Center Refresh Token – moiaune.dev by Mads Moi-Aune