5

I want to get an access token from an external endpoint (HTTP callout to REST API) without hardcoding passwords. The external system expects a request with Oauth 2.0 authentication details provided in the body, like the following:

String body = 'client_id='+EncodingUtil.urlEncode('myClientId','UTF-8');

body += '&client_secret='+EncodingUtil.urlEncode('myClientSecret','UTF-8');

body += '&grant_type='+EncodingUtil.urlEncode('password','UTF-8');

body += '&username='+EncodingUtil.urlEncode('myUsername','UTF-8');

body += '&password='+EncodingUtil.urlEncode('myPassword','UTF-8');

Hardcoded request is successful, but I'd like to use Named Credentials. I can set up an Auth. Provider of type Open ID Connect and provide client_id and client_secret. But there I cannot set parameters like 'username' and 'password' which are needed in order to make a proper request. This makes me wonder if that kind of authentication is possible in SF.

An alternative would be using Custom Settings, but then the credentials would be too easily accessible (and concrete setting cannot be deployed) which is not a good practice.

So my question is: Can I securely authenticate with above credentials using Apex without hardcoding them?

3
  • Related - see this wonderful post on Storing Tokens Securely. I'm currently implementing Daniels suggestion of Protected Custom Metadata Types Jul 8, 2019 at 13:43
  • Also, when creating a new Named Credential, you can try using the Allow Merge Fields in HTTP Header and/or the Allow Merge Fields in HTTP Body checkboxes to allow you to use tokens via merge fields Jul 8, 2019 at 13:49
  • I already set those checkboxes and tried to change authentication protocol to Username/Password in Named Credential. Then I used '{!$Credential.Username}' in Apex and the '{!$Credential.Password}' as well just to check if at least those 2 values could be not hardcoded. But I've been receiving an error response with body like: {"error":"invalid_grant","error_description":"invalid_username_or_password"}. I will have a look at Daniel's suggsestions.
    – moneo
    Jul 8, 2019 at 13:55

1 Answer 1

2

Out of the box, OpenID Connect authentication provider that SF ships does not support resource owner password grant type/flow (grant_type = password). So while you can create an instance of Named Credentials and set authentication protocol to oAuth 2.0, to perform a resource owner flow against a 3rd party resource you'll need to roll your own, custom authentication provider. That is my recommendation. Here's a good example to use as a starting point: JWT auth provider

You can use Named Credentials without an authentication provider. With oAuth as the protocol you'll be (mostly) rolling your own implementation. The only exception: JWT access tokens and JWT-based exchange flow; Named Credentials supports them natively. For all other oAuth flows and/or token formats Named Credentials is merely a placeholder, the work has to be performed by an authentication provider.

If you want to use Named Credentials without an authentication provider, it still offers some value versus coding everything in Apex. Namely, you can parameterize the target endpoint (URL) as well as username + password values required for resource grant flow. The latter can be done by using the Allow Merge Fields in HTTP Body feature of Named Credentials and setting authentication type to Password Auth.

If you squint at these two options, the second option (custom Apex classes + Named Credentials) is not a whole lot less work versus the first option (custom Auth provider + Named Credentials), thus my recommendation above.

3
  • My understanding is that as long as you can generate an access token / refresh token using the OAuth 2.0 flow (Im guessing SF uses Web Server Flow), that when you make a callout using the named credential, it will only use the refresh token flow if necessary and not ResourceOwner nor Web Server, or any other flow... Is that a fair assumption?
    – Z33dawg
    Apr 8, 2021 at 15:37
  • @Z33dawg Yes. Named Creds + out of the box auth provider encapsulate both authorization code grant (aka Web Server) and refresh flows. The latter will only work under a certain set of conditions - scope being one of them. They are two different flows but Named Creds handwaves them into one box.
    – identigral
    Apr 8, 2021 at 17:28
  • Okay thanks, because client said I need to use Resource Owner Flow, but as long as I was able to successfully authenticate successfully using the named credential/Named Principal Oauth, I should not have to custom code the Resource Owner flow and can continue to use Named Credentials as long as their refresh token does not expire.
    – Z33dawg
    Apr 8, 2021 at 20:50

You must log in to answer this question.

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