0
votes

I am running the following in Powershell. I am getting an error returned that "The given client credentials were not valid". I am trying to do the first step of using the API, generating the access token. I have confirmed that I have a valid client_id and client_secret.

This is working in Postman, but I am not seeing what I have wrong in Powershell. Help!

$URLTokenV2="https://accounts.adp.com/auth/oauth/v2/token?grant_type=client_credentials"
$Json= @{
    client_id='xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx'
    client_secret='xxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxxx'
}
$Json=$Json | ConvertTo-Json
$Cert = Get-ChildItem -Path "Cert:\LocalMachine\My" | Where-Object {$_.Subject -like "CN=CertCN*"}
$Response=Invoke-RestMethod -Uri $URLTokenV2 -Method Post -Body $Json -Certificate $Cert -ContentType 'application/x-www-form-urlencoded'

I have tried the same with Invoke-RestMethod and Invoke-WebRequest. I get the same result for both, that the client credentials are not valid.

Responses are appreciated. Thanks in advance.

2
Shouldn't that be -ContentType 'application/json' ?Theo
The documentation for the API call states it is supposed to be x-www-form-urlencoded. At your suggestion I tried application/json just for kicks. I got the same result as before. Thanks for the idea though.Kenny
Try passing the grant_type query parameter in the body (add it to the $JSON hashtable) instead of as part of the URI.Mathias R. Jessen
Well, I got that to work, but the URL is a little different. The URL is now "accounts.adp.com/auth/oauth/v2/token?" It didn't work previously without the '?' Thank you so much!Kenny

2 Answers

0
votes

From ADP's public documentation:

In general, your consumer application should pass the client_id and client_secret parameters in the HTTP Authorization header using the HTTP Basic authentication scheme (or other designated scheme). The client_id and client_secret must be separated by a single colon (":") character and encoded within a base64-encoded string, as required by IETF RFC 2617.

Your consumer application must:

  • Send the request with the X.509 certificate provided during registration.
  • Pass all parameters in a URL-encoded format with UTF-8 character encoding as specified by the HTTP header Content-Type: application/x-www-form-urlencoded. The actual request might look like the following example:
 POST /auth/oauth/v2/token HTTP/1.1
 Host: accounts.adp.com
 Authorization: Basic QURQVGFibGV0OnRoZXRhYmxldHBhc3N3b3Jk
 Content-Type: application/x-www-form-urlencoded
 grant_type=client_credentials

So you need to do something like this instead:

$URLTokenV2 = 'https://accounts.adp.com/auth/oauth/v2/token'

# Prepare Basic Authentication header payload (the base64 part)
$AuthorizationValue = [Convert]::ToBase64String(
  [System.Text.Encoding]::UTF8.GetBytes('xxxxxxxxx-client-id-xxxxxxxxx:xxxxxx-client-secret-xxxxxxxxxxxx')
)

$Cert = Get-ChildItem -Path "Cert:\LocalMachine\My" | Where-Object {$_.Subject -like "CN=CertCN*"}

# Prepare request body - no need to explicitly convert to JSON 
$Body = @{
  grant_type = 'client_credentials'
}

# Pass the `Authorization` header value with the payload we calculate from the id + secret
$Response = Invoke-RestMethod -Uri $URLTokenV2 -Method Post -Header @{ Authorization = "Basic ${AuthorizationValue}" } -Body $Body -Certificate $Cert -ContentType 'application/x-www-form-urlencoded'
0
votes

Following the comment from Mathias I now have the following working

$URLTokenV2="https://accounts.adp.com/auth/oauth/v2/token?"
$Json= @{
     client_id='xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx'
     client_secret='xxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxxxx'
     grant_type='client_credentials'
}
$Response=Invoke-RestMethod -Uri $URLTokenV2 -Method Post -Body $Json -Certificate $Cert -ContentType 'application/x-www-form-urlencoded'

I had tried "grant_type='client_credentials'" as a part of the Json array, but this time when I tried it I accidentally left the '?' in the URL. I also had to remove the line to convertto-Json. After that it worked.