8

I am having an issue when attempting to reference the {!$Credential.UserName} and {!$Credential.Password} merge fields.

I created a named credential with the following configuration:

  • Identity Type: Named Principal
  • Authentication Protocol: Password Authentication
  • Generate Authorization Header: false
  • Allow Merge Fields in HTTP Header: true
  • Allow Merge Fields in HTTP Body: false

I also set the username and password as the credentials expected by our vendor's API. I then define the Authorization Header keys in Apex and use the merge fields as reference.

        req.setHeader('Authorization-UserName', '{!$Credential.UserName}');
        req.setHeader('Authorization-Token', '{!$Credential.Password}');

I initially hard-coded the Authorization-UserName and Authorization-Token (which worked). I am also using the same endpoint that was defined in Remote Site Settings. But due to the fact that I plan to use Named Credentials, I disabled the end point in Remote Site Settings (see: Create Named Credentials to Define Callout Endpoints and Their Authentication Settings). It appears that the {!$Credential.UserName} is not resolving to the defined username value.

3
  • ,I am also facing the same issue. Did you find a solution for this issue. Commented Jan 13, 2017 at 2:42
  • I have not found a solution. I'll be sure to update this thread when I do.
    – structure
    Commented Jan 13, 2017 at 12:36
  • What does show up then? It sounds like {!$Credential.Password} merges properly?
    – Adrian Larson
    Commented Apr 26, 2017 at 21:36

3 Answers 3

4

I was running into a similar issue.

If you are doing a GET call make sure you don't append a body or your request will NOT work with even with the correct headers. If you are doing a POST the easiest was to append parameters is through the body.

Try feeding the username and password variables into a String before assigning them to setHeader values. Also see if using 'Credential.Username' instead of 'Credential.UserName' helps. What I use below is an example of a successful call:

HttpRequest req = new HttpRequest();
req.setEndpoint('callout:My_Named_Credential_Name/login_path'); //This tells 
salesforce which credential you are referencing
req.setMethod('POST'); 
String jsonBody ='client_id=' + '{!$Credential.Username}' + '&client_secret=' + '{!$Credential.Password}';
//Credential is a Keyword, NOT where you substitute the name of your credential
req.setBody(jsonBody);
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());

This should work for anyone that is trying to retrieve an access_token from an external API. The jsonBody will be positioned after the url as though it is query parameters.

If my Named credential url is: https://looker.randomDomainName.com:19999/api/3.0

The Url/Endpoint will come out to: https://looker.randomDomainName.com:19999/api/3.0/login_path?client_id=your_Named_Credential_Username&client_secret=your_Named_Credential_Password

I hope this helps!

1
  • Assigning to a string is the only way I could get the Named Credential to resolve to a usable header as well. Commented Jun 24, 2022 at 19:59
1

I was having the same issue, but I needed the username and password in the body of the request, I solved this by assigning the merge fields to string variables, then put the variables with all the other body content. You have to be aware that when you debug the variables or the body you will see the merge field '{!$Credential.UserName}' .... and not the actual value, the value is only replaced when the request is finally sent.

        Http h = new Http();
        HttpRequest req = new HttpRequest();
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.setMethod('POST');
        req.setEndpoint('callout:ePayData/api/transact.php');

        string username = '{!$Credential.UserName}';
        string password = '{!$Credential.Password}';

        string body = CreateRequestBody(acc);

        req.setBody('username='+ username + '&password=' + password + '&' + body);

        System.debug(req.getBody());
        HttpResponse res = h.send(req);
        String responseJson = res.getBody();

        System.debug(responseJson);
3
  • Is there any merge field to obtain the user's token? Commented May 30, 2017 at 18:26
  • @kleytman-aular So, when you say "you will see the merge field '{!$Credential.UserName}' .... and not the actual value, the value is only replaced when the request is finally sent", do you mean to say that there is no way to see the actual merge fields values in the debug logs?
    – Azeez
    Commented Aug 30, 2018 at 11:08
  • The values are not merged in until the "last mile" when the request is about to exit Salesforce. However if you need to prove to yourself (for debugging's sake) that it merges, you could use a service like PostBin or RequestBin to create a fake endpoint and it will show you the entire request that you sent to it.
    – Charles T
    Commented Nov 29, 2018 at 15:17
1

I ran into two things while trying to resolve this:

  1. The Apex API version needs to be 35 or above (winter '16). That's when support for the merge fields started.

  2. If you have a post request that includes the merge fields in the body then the headers should be set after request.setBody() is called. If you call setHeaders() before setBody() then the merge fields will not be merged. This will even fail if the named credential doesn't allow merge fields in the header. If your merge fields are in the header then this issue doesn't apply.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .