Posted by Abhishek on March 10, 2021
In traditional authentication, any client can connect to a server. The clients know the server which is why they can request the server for some action to be performed. The server doesn’t know which client is connecting to it. This is fine when server is hosting a website and client requests the website.
But if we have an API hosted on the server and we allow any client to access it, there is a hidden vulnerability that can possibly exploit the server since the server doesn’t know how to validate which client is allowed to talk to the server.
Two Way SSL was introduced to solve this security hole. This technique is also popularly known as “Mutual Authentication”. Here, the client has to present a certificate in the request to the server. Server will only allow the request to be processed if the server identifies & validates the certificate presented by the client. Therefore, server knows which clients will approach it and can deny all others who provide incorrect certificate or no certificate.
Salesforce wants to call a REST API exposed by an external system. External System imposes 2 way SSL on every request. The External System provides few certificates which has to be used by the client while initiating calls to it.
openssl pkcs12 -export -in cert.pem -inkey "privateKey.pem" -certfile cert.pem -out myBundle.p12
keytool -importkeystore -srckeystore myBundle.p12 -srcstoretype PKCS12 -destkeystore myBundle.jks
keytool -list -v -keystore myBundle.jks
keytool -keystore myBundle.jks -changealias -alias 1 -destalias MYBUNDLE
keytool -import -alias ejbca -keystore myBundle.jks -file SYSCA.pem -storepass mybundle123
keytool -import -alias digicert -keystore myBundle.jks -file RootCA.crt -storepass mybundle123
Now, you have a jks bundle which houses the application cert, sysCA cert & rootCA cert. This is now called a JKS with certificate chain.
Navigate to Setup -> Security -> Named Credentials and create a New Named Credential as shown below.
Assumption here is that External System uses Username-Password Authentication. Based on your use-case, you can change the Authentication Protocol.
HttpRequest req = new HttpRequest();
req.setEndpoint('callout:External_System/users');
req.setMethod('GET');
Http http = new Http();
HTTPResponse res = http.send(req);
System.debug(res.getBody());
Without the MYBUNDLE certificate in the Named Credential, the same code when executed will throw an error.