A reusable Auth Provider that can be used with named / external credentials that executes an OAuth 2.0 JWT Client Authentication flow using a Client Credentials grant type.
The grant type standards are described in https://datatracker.ietf.org/doc/html/rfc7523#section-2.2
Since the Winter 24 release (API v59.0) Salesforce Named Credentials natively Support this flow making this Auth Provider Solution Obsolete for System Integrations using Named Principals.
A reason to keep using this Auth Provider is you need a Per User principal based on the JWT Subject or send custom headers to the token endpoint.
The following package need to be installed first before installing this package. (In this order) If you use the managed package you need to installed the managed package dependency and if you use the unlocked version you need to use the unlocked dependency. | Info | Value |
---|---|---|
Name | Lightweight - Apex Unit Test Util v2 | |
Version | 2.4.0-1 | |
Managed Installation URL | /packaging/installPackage.apexp?p0=04tP3000000M6OXIA0 | |
Unlocked Installation URL | /packaging/installPackage.apexp?p0=04tP3000000M6Q9IAK | |
Github URL | https://github.com/jfwberg/lightweight-apex-unit-test-util-v2 | |
Name | Lightweight - Apex REST Util | |
Version | 0.11.0-1 | |
Managed Installation URL | /packaging/installPackage.apexp?p0=04tP3000000M6gHIAS | |
Unlocked Installation URL | /packaging/installPackage.apexp?p0=04tP3000000M6htIAC | |
Github URL | https://github.com/jfwberg/lightweight-apex-rest-util |
This package has an extension that adds a basic (error) logging functionality and a user mapping utility that allows the Auth Provider to work in a user context using "Per User" instead of "Named Principal". | Info | Value |
---|---|---|
Name | Lightweight - Auth Provider Util v2 | |
Version | 0.12.0-1 | |
Managed Installation URL | /packaging/installPackage.apexp?p0=04tP3000000MVUzIAO | |
Unlocked Installation URL | /packaging/installPackage.apexp?p0=04tP3000000MW1FIAW | |
GIT URL | https://github.com/jfwberg/lightweight-auth-provider-util |
Info | Value |
---|---|
Name | Lightweight - OAuth JWT Client Credentials Auth Provider |
Version | 0.5.0-1 |
Managed Installation URL | /packaging/installPackage.apexp?p0=04tP3000000MWfZIAW |
Unlocked Installation URL | /packaging/installPackage.apexp?p0=04tP3000000MWndIAG |
Since the Spring 24 release platform events started running as the Automated Process User. Making the logging fail due to access issue. To fix this I created a specific permission set for this user that can be assigned using the code below.
insert new PermissionSetAssignment(
AssigneeId = [SELECT Id FROM User WHERE alias = 'autoproc']?.Id,
PermissionSetId = [SELECT Id FROM PermissionSet WHERE Name = 'Lightweight_Auth_Provider_Util_AutoProc']?.Id
);
In my example I am going to connect an api called "PiMoria"; this my test domain that I will use throughout this example.
In setup > Auth Providers > Create a new Auth. Provider Using the OAuthJwtClientCredentials class as the type
Populate the Execute Registration As field first, this is a mandatory field that is not marked as mandatory and will reset the entire form if you forget it.
Populate the fields in the the Auth. Provider. The below table details what is required in the fields
Triple check you put in all mandatory fields: If you have forgotten one, you have to re-do them all
Field Name | Description | Example |
---|---|---|
Name | Auth Provider API Name | PiMoria PROD |
URL Suffix | The URL suffix that is used in the callback URL Make sure this is the same as the name field | PiMoria |
Additional Token Endpoint Headers | Optional headers that are send during the API token request. Key value pairs are split with a comma and header key values are set using a colon | apiId : echo, apiKey : 1919 |
Additional Token Endpoint Parameters | Optional POST body parameters that are send during the API token request. Key value pairs are split with a comma and parameter key values are set using a colon | tenant : 12-345, client_id : ab-cde |
Auth Provider Name | The name of the Auth Provider: !! This must be the same as the Name field !! | PiMora |
JWT Algorithm | The algoritm used for signing the JWT. Valid values are: 'RS256','RS384','RS512','ES256','ES384','ES512' Note: we are limited to the algorithms supported by the Crypto Class | RS512 |
JWT Audience | The aud in the JWT | https://prod.pimoria.com |
JWT Issuer | The iss in the JWT | pimoria-client-api-identifier |
JWT Kid | The Key Id in the JWT | prod-1 |
JWT Signing Algorithm | The algorithm used to sign the JWT and generate a JWS 'RSA-SHA256','RSA-SHA384','RSA-SHA512','ECDSA-SHA256','ECDSA-SHA384','ECDSA-SHA512' | RSA-SHA512 |
JWT Signing Certificate Name | The certificate API name that is used for signing the certificate | PiMoriaProd |
JWT Subject | The sub field in the JWT | system.user@pimoria.com |
Token Endpoint URL | The URL for the token endpoint, usually ends in /oauth2/token | https://prod.pimoria.com/oauth2/token |
Scope | Optional value for the scope parameter in the request body | api,refresh_token |
Custom Callback URL | Optionally you can add your custom callback URL, this should not be required. The code generates the callback URL based on the name | |
Enable Error Logging | Optionally error logging can be enabled to log any errors thrown during the get token process | |
Enable Per User Mode | Optionally the Auth Provider allows for Per User mode instead of Named Principal, to allow for user APIs that require user context. A mapping needs to be setup. | |
Enable Per User Login Logging | Optionally you can add your custom callback URL, this should not be required. The code generates the callback URL based on the name |
When finished it should look like something like this
In order to make API call-outs to the token endpoint securely, we must setup a remote site setting for the token endpoint.
External Credentials require a Permission Set in order to create a credential type mapping. It's best practice to create a separate Permisison Set for each Extern Credential to keep a strict separation and stick to the least access principle. At this stage you don't have to assign any permissions, this will happen later.
Your Auth Provider is now ready for testing. The next step is to create an External Credential that authenticates to the token endpoint using the Auth Provider.
You have no finished setting up the external credetials and the auth provider it's time to test it by callign the token endpoint and authenticate.
Once you have successfully authenticated your external credential and you want to use this connection from Apex or Flows to call an API we'll need a Named Credential
Now you have everything you need. Let's open up and execute anonymous window and call one of our endpoints.
HttpRequest request = new HttpRequest();
request.setEndPoint('callout:PiMoria/api/authentication-test');
request.setMethod('POST');
HttpResponse response = new HTTP().send(request);
System.debug(response.getBody());
In some cases there is a bug in the certificate import that gives an error if you try to import a JKS It says "Data Not Available". I have this issue in all my scratch orgs. There is a simple way to resolve this. 1) Go to setup > certificate and key management 2) Create a self signed certficate 3) Go to Setup >> Identity provider 4) Click enable Identity Provider and select the self signed certificate you just created and press save 5) Press the disable button, as we dont really need it 6) Go back to Setup > Certificate and Key Management and try to "import from keystore" again, it should work now.