[SalesForce] Using Named Credentials in OAuth 2 authentication (grant_type=password)

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?

Best Answer

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.