3

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?

  • Related - see this wonderful post on Storing Tokens Securely. I'm currently implementing Daniels suggestion of Protected Custom Metadata Types – Brian Miller Jul 8 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 – Brian Miller Jul 8 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 at 13:55
1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.