Setting the header properties for OAuth2 token request

I'm putting together a process in Salesforce to work with PureCloud campaigns, and as it's the first OAuth process into PureCloud I've built I'm requesting some guidance. At this point I'm getting 'Bad Request' as the response, so (hopefully) it's something small and naive on my part that can be easily remedied. (I will cross-post this over on Stack Exchange to see if there are other Salesforce developers that have worked with the Platform API.)

At the moment, I'm just putting together the request for an access token, and one piece that doesn't appear to be setting correctly is the grant_type. When I try to verify the header, I'm seeing null there.

The example for getting the access token is:

POST /oauth/token HTTP/1.1
Host: login.mypurecloud.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic BASE64(<client_id>:<client_secret>)

grant_type=client_credentials

In Apex, the code is as follows:
HttpRequest req = new HttpRequest();

    req.setMethod('POST');
    
    req.setHeader('Host','login.mypurecloud.com/oauth');
    req.setHeader('content-type', 'application/x-www-form-urlencoded');
    req.setHeader('authorization', 'Basic BASE64(' + clientId + ':' + clientSecret + ')');
    req.setHeader('grant_type', 'client_credentials');
    req.setEndpoint('https://login.mypurecloud.com/oauth/token');

When I output the header, I get the following:

Method:POST
grant_type null
authorization Basic BASE64(--clientID--:--clientSecret--)
content-type application/x-www-form-urlencoded
Host login.mypurecloud.com/oauth
System.HttpRequest[Endpoint=https://login.mypurecloud.com/oauth/token, Method=POST]

So right now, it looks like the grant_type setting is invalid, at a minimum. Let me know if anything else jumps out at you, and thanks!

grant_type isn't a header, it's a form data property.

Is it necessary? I don't see any methods related to setting that in Apex (I've outlined my options, below). Is there anything else that seems off?

getBody()
Retrieves the body of this request.
getBodyAsBlob()
Retrieves the body of this request as a Blob.
getBodyDocument()
Retrieves the body of this request as a DOM document.
getCompressed()
If true, the request body is compressed, false otherwise.
getEndpoint()
Retrieves the URL for the endpoint of the external server for this request.
getHeader(key)
Retrieves the contents of the request header.
getMethod()
Returns the type of method used by HttpRequest.
setBody(body)
Sets the contents of the body for this request.
setBodyAsBlob(body)
Sets the contents of the body for this request using a Blob.
setBodyDocument(document)
Sets the contents of the body for this request. The contents represent a DOM document.
setClientCertificate(clientCert, password)
This method is deprecated. Use setClientCertificateName instead.
setClientCertificateName(certDevName)
If the external service requires a client certificate for authentication, set the certificate name.
setCompressed(flag)
If true, the data in the body is delivered to the endpoint in the gzip compressed format. If false, no compression format is used.
setEndpoint(endpoint)
Specifies the endpoint for this request.
setHeader(key, value)
Sets the contents of the request header.
setMethod(method)
Sets the type of method to be used for the HTTP request.
setTimeout(timeout)
Sets the timeout in milliseconds for the request.
toString()
Returns a string containing the URL for the endpoint of the external server for this request and the method used, for example, Endpoint=http://YourServer, Method=POST

Okay, thank you -- I've adjusted that and now I see that I/we aren't authorized to use client credentials. Is that a setting I can get to in Admin, or can it be addressed if we submit a ticket? Or do I need to use a different mode of authentication?

STATUS_CODE:{"error":"unauthorized_client","description":"client is not authorized to use the client_credential grant type"}

Here's some info on creating an OAuth client: https://developer.mypurecloud.com/api/rest/authorization/create-oauth-client-id.html

When you create it, be sure to choose the Client Credentials grant type and assign it a role with appropriate permissions; your user account's permissions have zero bearing on the permissions for the client credentials.

Referring to the grant_type body parameter? Absolutely. I'm not very familiar with scripting in SalesForce, but I'm guessing you can use the setBody(body) function with the value grant_type=client_credentials. The content-type header looks correct. I would research information about how to send form encoded data in a SalesForce POST request if that doesn't work.

Argh -- I could've sworn the client that I looked at was set up that way ... but no. I'll create a new one.

Actually creating an OAuth client with the appropriate Role and running the following code does the trick!

HttpRequest req = new HttpRequest();
req.setMethod('POST');
    
    req.setHeader('Authorization', 'Basic ' +
      EncodingUtil.base64Encode(Blob.valueOf(clientId + ':' + clientSecret)));
    req.setHeader('Host','https://login.mypurecloud.com/oauth');
    req.setHeader('content-type', 'application/x-www-form-urlencoded');
    req.setEndpoint('https://login.mypurecloud.com/oauth/token');

	req.setBody('grant_type=client_credentials');

    Http http = new Http();
    
    try{
       	HTTPResponse res = http.send(req);
        
    } catch(System.CalloutException e){
        // do something useful here
    }
1 Like

This topic was automatically closed 31 days after the last reply. New replies are no longer allowed.